"use strict"; { /** * @typedef {InstanceType} Player * @typedef {InstanceType} Card * @typedef {InstanceType} VCard * @typedef {InstanceType} GameEvent * @typedef {InstanceType} NodeWS */ const userAgent=navigator.userAgent.toLowerCase(); if(!localStorage.getItem('gplv3_noname_alerted')){ if(confirm('①无名杀是一款基于GPLv3协议的开源软件!\n你可以在遵守GPLv3协议的基础上任意使用,修改并转发《无名杀》,以及所有基于《无名杀》开发的拓展。\n点击“确定”即代表您认可并接受GPLv3协议↓️\nhttps://www.gnu.org/licenses/gpl-3.0.html\n②无名杀官方发布地址仅有GitHub仓库!\n其他所有的所谓“无名杀”社群(包括但不限于绝大多数“官方”QQ群、QQ频道等)均为玩家自发组织,与无名杀官方无关!')){ localStorage.setItem('gplv3_noname_alerted',true); } else{ const ios=userAgent.includes('iphone')||userAgent.includes('ipad')||userAgent.includes('macintosh'); //electron if(typeof window.process=='object'&&typeof window.require=='function'){ const versions=window.process.versions; const electronVersion=parseFloat(versions.electron); let remote; if(electronVersion>=14){ remote=require('@electron/remote'); }else{ remote=require('electron').remote; } const thisWindow=remote.getCurrentWindow(); thisWindow.destroy(); window.process.exit(); } //android-cordova环境 //ios-cordova环境或ios浏览器环境 //非ios的网页版 else if(!ios){ window.close(); } } } const nonameInitialized=localStorage.getItem('noname_inited'); const GeneratorFunction=(function*(){}).constructor; // gnc: GeNCoroutine const gnc={ of:fn=>gnc.is.generatorFunc(fn)?function genCoroutine(){ let gen=fn.apply(this,arguments); gen.status="next"; gen.state=undefined; const callback=(resolve,reject)=>{ let result, nexts=resolve, throws=reject; try{ result=gen[gen.status](gen.state); }catch(error){ reject(error); return; } if(!result.done){ nexts=(item)=>{ gen.state=item; gen.status="next"; callback(resolve,reject); } throws=(err)=>{ gen.state=err; gen.status="throw"; callback(resolve,reject); } } result=result.value; Promise.resolve(result).then(nexts,throws); } return new Promise(callback); }:(()=>{throw new TypeError("gnc.of needs a GeneratorFunction.")})(), is:{ coroutine:item=>typeof item=="function"&&item.name=="genCoroutine", generatorFunc:item=>item instanceof GeneratorFunction, generator:item=>(typeof item=="object")&&("constructor" in item)&&item.constructor&&("constructor" in item.constructor)&&item.constructor.constructor===GeneratorFunction } }; const _status={ paused:false, paused2:false, paused3:false, over:false, clicked:false, auto:false, /** * @type {GameEvent} */ event:null, ai:{}, lastdragchange:[], skillaudio:[], dieClose:[], dragline:[], dying:[], globalHistory:[{ cardMove:[], custom:[], useCard:[], changeHp:[], everything:[], }], cardtag:{ yingbian_zhuzhan:[], yingbian_kongchao:[], yingbian_fujia:[], yingbian_canqu:[], yingbian_force:[] }, renku:[], prehidden_skills:[], postReconnect:{}, }; const lib={ configprefix:'noname_0.9_', versionOL:27, updateURLS:{ coding:'https://raw.fgit.cf/libccy/noname', github:'https://raw.githubusercontent.com/libccy/noname', }, updateURL:'https://raw.githubusercontent.com/libccy/noname', mirrorURL:'https://raw.fgit.cf/libccy/noname', hallURL:'47.99.105.222', assetURL:typeof nonameInitialized!='string'||nonameInitialized=='nodejs'?'':nonameInitialized, userAgent:userAgent, compatibleEdition:Boolean(typeof nonameInitialized=='string'&&nonameInitialized.match(/\/(?:com\.widget|yuri\.nakamura)\.noname\//)), changeLog:[], updates:[], canvasUpdates:[], video:[], skilllist:[], connectBanned:[], characterIntro:{}, characterTitle:{}, characterPack:{}, characterFilter:{}, characterSort:{}, characterReplace:{}, characterGuozhanFilter:["mode_guozhan"], dynamicTranslate:{}, cardPack:{}, skin:{}, onresize:[], onphase:[], onwash:[], onover:[], ondb:[], ondb2:[], chatHistory:[], emotionList:{ xiaowu_emotion:14, xiaokuo_emotion:8, shibing_emotion:15, guojia_emotion:20, zhenji_emotion:20, xiaosha_emotion:20, xiaotao_emotion:20, xiaojiu_emotion:20, }, animate:{ skill:{}, card:{}, }, onload:[], onload2:[], onprepare:[], arenaReady:[], onfree:[], inpile:[], inpile_nature:[], extensions:[], extensionPack:{}, cardType:{}, hook:{globaltrigger:{},globalskill:{}}, //函数钩子 hooks:{ // 本体势力的颜色 addGroup:[(id,_short,_name,config)=>{ if("color" in config&&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; const g1=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}"`) ) ); const g2=cs.group( cs.of( "div", cs.isAttr("data-nature",`"${id}m"`) ), cs.of( "span", cs.isAttr("data-nature",`"${id}m"`) ) ); const g3=cs.group( cs.of( "div", cs.isAttr("data-nature",`"${id}mm"`) ), cs.of( "span", cs.isAttr("data-nature",`"${id}mm"`) ) ); let result={}; result[g1]={ 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` ) }; result[g2]={ 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" ) }; result[g3]={ 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" ) }; game.dynamicStyle.addObject(result); lib.groupnature[id]=id; } } if(typeof config.image=='string') Object.defineProperty(lib.card,`group_${id}`,{ configurable:true, enumerable:false, writable:true, value:{ fullskin:true, image:config.image } }); }], //增加新属性杀 addNature:[(nature,_translation,config)=>{ if(typeof config!='object') config={}; let linked=config.linked,order=config.order,background=config.background,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${item[1].slice(1, 3)}`); let c2=parseInt(`0x${item[1].slice(3, 5)}`); let c3=parseInt(`0x${item[1].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()})` ), }; 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()})`, }; game.dynamicStyle.addObject(result2); } }], }, announce:{ init(){ _status._announce=document.createElement("Announce"); _status._announce_cache=new Map(); delete lib.announce.init; }, //推送一个对象给所有监听了name的订阅者。 publish(name,values){ if(_status._announce) _status._announce.dispatchEvent(new CustomEvent(name,{ detail:values })); return values; }, //订阅name相关的事件。 subscribe(name,method){ if(_status._announce&&_status._announce_cache) { let subscribeFunction; if(_status._announce_cache.has(method)){ let records=_status._announce_cache.get(method); subscribeFunction=records.get("Listener"); records.get("EventTargets").add(name); } else{ subscribeFunction=event=>method(event.detail); let records=new Map(); records.set("Listener",subscribeFunction); records.set("EventTargets",[name]); _status._announce_cache.set(method,records); } _status._announce.addEventListener(name,subscribeFunction); } return method; }, //取消对事件name的订阅 unsubscribe(name,method){ if(_status._announce&&_status._announce_cache&&_status._announce_cache.has(method)){ let records=_status._announce_cache.get(method); const listener=records.get("Listener"); let eventTargets=records.get("EventTargets"); eventTargets.remove(name); if(eventTargets.length<=0) _status._announce_cache.remove(method); _status._announce.removeEventListener(name,listener); } return method; } }, objectURL:new Map(), hookmap:{}, imported:{}, layoutfixed:['chess','tafang','stone'], pinyins:{ _metadata:{ shengmu:['zh','ch','sh','b','p','m','f','d','t','l','n','g','k','h','j','q','x','r','z','c','s','y','w'], special_shengmu:['j','q','x','y'], feijiemu:{ i:['ing','iu','ie','in'], u:['ui','un'], ü:['üe','ün'], }, zhengtirendu:['zhi','chi','shi','ri','zi','ci','si'], yunjiao:{ '一麻':['a','ia','ua'], '二波':['o','e','uo'], '三皆':['ie','üe'], '四开':['ai','uai'], '五微':['ei','ui'], '六豪':['ao','iao'], '七尤':['ou','iu'], '八寒':['an','ian','uan','üan'], '九文':['en','in','un','ün'], '十唐':['ang','iang','uang'], '十一庚':['eng','ing','ong','ung'], '十二齐':['i','er','ü'], '十三支':['-i'], '十四姑':['u'], }, } }, /** * Yingbian * * 应变 */ yingbian:{ condition:{ color:new Map([ ['zhuzhan','wood'], ['kongchao','soil'], ['fujia','orange'], ['canqu','fire'], ['force','metal'] ]), complex:new Map([ ['zhuzhan',function(event){ const yingbianZhuzhan=game.createEvent('yingbianZhuzhan'); yingbianZhuzhan.player=event.player; yingbianZhuzhan.card=event.card; yingbianZhuzhan._trigger=event; yingbianZhuzhan.yingbianZhuzhanAI=event.yingbianZhuzhanAI; yingbianZhuzhan.afterYingbianZhuzhan=event.afterYingbianZhuzhan; yingbianZhuzhan.setContent(()=>{ 'step 0' event._global_waiting=true; event.send=(player,card,source,targets,id,id2,yingbianZhuzhanAI,skillState)=>{ if(skillState) player.applySkills(skillState); var type=get.type2(card),str=get.translation(source); if(targets&&targets.length) str+=`对${get.translation(targets)}`; str+=`使用了${get.translation(card)},是否弃置一张${get.translation(type)}为其助战?`; player.chooseCard({ filterCard:(card,player)=>get.type2(card)==type&&lib.filter.cardDiscardable(card,player), prompt:str, position:'h', _global_waiting:true, id:id, id2:id2, ai:typeof yingbianZhuzhanAI=='function'?yingbianZhuzhanAI(player,card,source,targets):cardx=>{ var info=get.info(card); if(info&&info.ai&&info.ai.yingbian){ var ai=info.ai.yingbian(card,source,targets,player); if(!ai) return 0; return ai-get.value(cardx); } else if(get.attitude(player,source)<=0) return 0; return 5-get.value(cardx); } }); if(!game.online) return; _status.event._resultid=id; game.resume(); }; 'step 1' var type=get.type2(card); event.list=game.filterPlayer(current=>current!=player&¤t.countCards('h')&&(_status.connectMode||current.hasCard(cardx=>get.type2(cardx)==type,'h'))).sortBySeat(_status.currentPhase||player); event.id=get.id(); 'step 2' if(!event.list.length) event.finish(); else if(_status.connectMode&&(event.list[0].isOnline()||event.list[0]==game.me)) event.goto(4); else event.send(event.current=event.list.shift(),event.card,player,trigger.targets,event.id,trigger.parent.id,trigger.yingbianZhuzhanAI); 'step 3' if(result.bool){ event.zhuzhanresult=event.current; event.zhuzhanresult2=result; if(event.current!=game.me) game.delayx(); event.goto(8); } else event.goto(2); 'step 4' var id=event.id,sendback=(result,player)=>{ if(result&&result.id==id&&!event.zhuzhanresult&&result.bool){ event.zhuzhanresult=player; event.zhuzhanresult2=result; game.broadcast('cancel',id); if(_status.event.id==id&&_status.event.name=='chooseCard'&&_status.paused) return ()=>{ event.resultOL=_status.event.resultOL; ui.click.cancel(); if(ui.confirm) ui.confirm.close(); }; } else if(_status.event.id==id&&_status.event.name=='chooseCard'&&_status.paused) return ()=>event.resultOL=_status.event.resultOL; },withme=false,withol=false,list=event.list; for(var i=0;i{ if(value!=player) value.showTimer(); }); event.withol=withol; 'step 5' if(!result||!result.bool||event.zhuzhanresult) return; game.broadcast('cancel',event.id); event.zhuzhanresult=game.me; event.zhuzhanresult2=result; 'step 6' if(event.withol&&!event.resultOL) game.pause(); 'step 7' game.players.forEach(value=>value.hideTimer()); 'step 8' if(event.zhuzhanresult){ var target=event.zhuzhanresult; target.line(player,'green'); target.discard(event.zhuzhanresult2.cards).discarder=target; if(typeof event.afterYingbianZhuzhan=='function') event.afterYingbianZhuzhan(event,trigger); var yingbianCondition=event.name.slice(8).toLowerCase(),yingbianConditionTag=`yingbian_${yingbianCondition}_tag`; target.popup(yingbianConditionTag,lib.yingbian.condition.color.get(yingbianCondition)); game.log(target,'响应了',player,'发起的',yingbianConditionTag); target.addExpose(0.2); event.result={ bool:true } } else event.result={ bool:false }; }); yingbianZhuzhan._args=Array.from(arguments); return yingbianZhuzhan; }] ]), simple:new Map([ ['kongchao',event=>!event.player.countCards('h')], ['fujia',event=>event.player.isMaxHandcard()], ['canqu',event=>event.player.getHp()==1] ]) }, effect:new Map([ ['add',()=>{ trigger.yingbian_addTarget=true; }], ['remove',()=>{ trigger.yingbian_removeTarget=true; }], ['damage',()=>{ if(typeof trigger.baseDamage!='number') trigger.baseDamage=1; trigger.baseDamage++; game.log(card,'的伤害值基数+1'); }], ['draw',()=>{ player.draw(); }], ['gain',()=>{ const cardx=trigger.respondTo; if(cardx&&cardx[1]&&cardx[1].cards&&cardx[1].cards.filterInD('od').length) player.gain(cardx[1].cards.filterInD('od'),'gain2'); }], ['hit',()=>{ trigger.directHit.addArray(game.players).addArray(game.dead); game.log(card,'不可被响应'); }], ['all',()=>{ card.yingbian_all=true; game.log(card,'执行所有选项'); }] ]), prompt:new Map([ ['add','目标+1'], ['remove','目标-1'], ['damage','伤害+1'], ['draw','摸一张牌'], ['gain','获得响应的牌'], ['hit','此牌不可被响应'], ['all','无视条件执行所有选项'] ]) }, /** * Stratagem buff * * 谋攻强化 */ stratagemBuff:{ cost:new Map([ ['sha',1], ['shan',1], ['juedou',2], ['huogong',2], ['tao',3] ]), effect:new Map([ ['sha',event=>{ if(event.step!=1) return; game.log(event.player,'触发了强化效果'); game.log(event.card,'抵消所需要的',new lib.element.VCard({ name:'shan' }),'数+1'); const map=event.customArgs; game.players.concat(game.dead).forEach(current=>{ const id=current.playerid; if(!map[id]) map[id]={}; if(typeof map[id].shanRequired=='number') map[id].shanRequired++; else map[id].shanRequired=2; }); }], ['shan',event=>{ if(event.step!=1) return; game.log(event.player,'触发了强化效果'); game.log('使用',event.card,'时视为两张',new lib.element.VCard({ name:'shan' }),'的效果'); event.player.when('useCard').filter(evt=>evt==event).then(()=>{ trigger.getParent(2).decrease('shanRequired',1); }); }], ['juedou',event=>{ if(event.step!=1) return; game.log(event.player,'触发了强化效果'); game.log('对',event.card,'的目标造成伤害时,伤害+1'); event.player.when({ source:'damageBegin1' }).filter(evt=>evt.getParent(2)==event&&event.targets.includes(evt.player)).then(()=>{ trigger.increase('num'); }); }], ['huogong',event=>{ if(event.step!=1) return; game.log(event.player,'触发了强化效果'); game.log(event.card,'造成的伤害+1'); event.increase('baseDamage',1); }], ['tao',event=>{ if(event.step!=1) return; game.log(event.player,'触发了强化效果'); game.log(event.card,'回复的体力+1'); event.increase('baseDamage',1); }] ]), prompt:new Map([ [ 'sha', /** * @type {() => string} */ ()=>`抵消所需要的【${get.translation('shan')}】数+1。` ], [ 'shan', /** * @type {() => string} */ ()=>`使用时视为两张【${get.translation('shan')}】的效果。` ], [ 'juedou', ()=>'对此牌的目标造成伤害时,伤害+1。' ], [ 'huogong', ()=>'造成的伤害+1。' ], [ 'tao', ()=>'回复的体力+1。' ] ]) }, /** * The actual card name * * 实际的卡牌名称 */ actualCardName:new Map([ ['挟令','挟天子以令诸侯'], ['霹雳投石车','霹雳车'] ]), characterDialogGroup:{ '收藏':function(name,capt){ return lib.config.favouriteCharacter.includes(name)?capt:null; }, '最近':function(name,capt){ var list=get.config('recentCharacter')||[]; return list.includes(name)?capt:null; } }, listenEnd:function(node){ if(!node._listeningEnd){ node._listeningEnd=true; node.listenTransition(function(){ delete node._listeningEnd; if(node._onEndMoveDelete){ node.moveDelete(node._onEndMoveDelete); } else if(node._onEndDelete){ node.delete(); } node._transitionEnded=true; }); } }, configMenu:{ general:{ name:'通用', config:{ mount_combine:{ name:'合并坐骑栏', init:false, intro:'
  • 将进攻坐骑栏和防御坐骑栏合并为同一个位置(重启后生效)。', restart:true, }, low_performance:{ name:'流畅模式', init:false, intro:'减少部分游戏特效,提高游戏速度', onclick:function(bool){ game.saveConfig('low_performance',bool); if(bool){ ui.window.classList.add('low_performance'); } else{ ui.window.classList.remove('low_performance'); } } }, compatiblemode:{ name:'兼容模式', init:false, intro:'开启兼容模式可防止扩展使游戏卡死并提高对旧扩展的兼容性,但对游戏速度有一定影响,若无不稳定或不兼容的扩展建议关闭', onclick:function(bool){ game.saveConfig('compatiblemode',bool); if(bool){ ui.window.classList.add('compatiblemode'); } else{ ui.window.classList.remove('compatiblemode'); } } }, confirm_exit:{ name:'确认退出', init:false, unfrequent:true, intro:'离开游戏前弹出确认对话框', }, keep_awake:{ name:'屏幕常亮', init:false, unfrequent:true, intro:'防止屏幕自动关闭
    注:旧版本通过NoSleep.js实现的屏幕常亮可能会影响外置音频的音量', onclick:function(bool){ game.saveConfig('keep_awake',bool); if(bool){ if(window.plugins&&window.plugins.insomnia) window.plugins.insomnia.keepAwake(); else if(window.noSleep){ document.addEventListener(lib.config.touchscreen?'touchend':'click', function enableNoSleepX() { document.removeEventListener(lib.config.touchscreen?'touchend':'click', enableNoSleepX, false); window.noSleep.enable(); }, false); } } else{ if(window.plugins&&window.plugins.insomnia) window.plugins.insomnia.allowSleepAgain(); else if(window.noSleep) window.noSleep.disable(); } } }, auto_confirm:{ name:'自动确认', init:true, unfrequent:true, intro:'当候选目标只有1个时,点击目标后无需再点击确认', }, skip_shan:{ name:'无闪自动取消', init:false, unfrequent:true, intro:'当自己需要使用或打出【闪】时,若自己没有【闪】,则跳过该步骤', }, unauto_choose:{ name:'拆顺手牌选择', init:false, unfrequent:true, intro:'拆牌或者顺牌时,就算只能选择对方的手牌依然手动选择', }, wuxie_self:{ name:'不无懈自己', init:true, unfrequent:true, intro:'自己使用的单目标普通锦囊即将生效时,不询问无懈', }, tao_enemy:{ name:'不对敌方出桃', init:false, intro:'双方阵营明确的模式中(如对决),敌方角色濒死时不询问出桃', unfrequent:true, }, enable_drag:{ name:'启用拖拽', init:true, intro:'按住卡牌后可将卡牌拖至目标', unfrequent:true, }, enable_dragline:{ name:'拖拽指示线', init:true, unfrequent:true, intro:'拖拽时显示虚线,可能降低游戏速度', }, enable_touchdragline:{ name:'拖拽指示线', init:false, unfrequent:true, intro:'拖拽时显示虚线,可能降低游戏速度', }, // enable_pressure:{ // name:'启用压感', // init:false, // intro:'开启后可通过按压执行操作', // unfrequent:true, // }, // pressure_taptic:{ // name:'触觉反馈', // init:false, // intro:'开启后按压操作执行时将产生震动', // unfrequent:true, // }, // pressure_click:{ // name:'按压操作', // init:'pause', // intro:'在空白区域按压时的操作', // unfrequent:true, // item:{ // pause:'暂停', // config:'选项', // auto:'托管', // } // }, touchscreen:{ name:'触屏模式', init:false, restart:true, unfrequent:true, intro:'开启后可使触屏设备反应更快,但无法使用鼠标操作', onclick:function(bool){ if(get.is.nomenu('touchscreen',bool)) return false; game.saveConfig('touchscreen',bool); } }, swipe:{ name:'滑动手势', init:true, unfrequent:true, intro:'在非滚动区域向四个方向滑动可执行对应操作', }, swipe_down:{ name:'下划操作', init:'menu', unfrequent:true, intro:'向下滑动时执行的操作', item:{ system:'显示按钮', menu:'打开菜单', pause:'切换暂停', auto:'切换托管', chat:'显示聊天', off:'关闭', }, onclick:function(item){ if(get.is.nomenu('swipe_down',item)) return false; game.saveConfig('swipe_down',item); } }, swipe_up:{ name:'上划操作', intro:'向上滑动时执行的操作', init:'auto', unfrequent:true, item:{ system:'显示按钮', menu:'打开菜单', pause:'切换暂停', auto:'切换托管', chat:'显示聊天', off:'关闭', }, onclick:function(item){ if(get.is.nomenu('swipe_up',item)) return false; game.saveConfig('swipe_up',item); } }, swipe_left:{ name:'左划操作', intro:'向左滑动时执行的操作', init:'system', unfrequent:true, item:{ system:'显示按钮', menu:'打开菜单', pause:'切换暂停', auto:'切换托管', chat:'显示聊天', off:'关闭', }, onclick:function(item){ if(get.is.nomenu('swipe_left',item)) return false; game.saveConfig('swipe_left',item); } }, swipe_right:{ name:'右划操作', intro:'向右滑动时执行的操作', init:'system', unfrequent:true, item:{ system:'显示按钮', menu:'打开菜单', pause:'切换暂停', auto:'切换托管', chat:'显示聊天', off:'关闭', }, onclick:function(item){ if(get.is.nomenu('swipe_right',item)) return false; game.saveConfig('swipe_right',item); } }, round_menu_func:{ name:'触屏按钮操作', intro:'点击屏幕中圆形按钮时执行的操作', init:'system', unfrequent:true, item:{ system:'显示按钮', menu:'打开菜单', pause:'切换暂停', auto:'切换托管' }, onclick:function(item){ if(get.is.nomenu('round_menu_func',item)) return false; game.saveConfig('round_menu_func',item); }, }, show_splash:{ name:'显示开始界面', intro:'游戏开始前进入模式选择画面', init:'init', item:{ off:'关闭', init:'首次启动', always:'保持开启', } }, game_speed:{ name:'游戏速度', init:'mid', item:{ vslow:'慢', slow:'较慢', mid:'中', fast:'较快', vfast:'快', vvfast:'很快', }, intro:'设置不同游戏操作间的时间间隔' }, sync_speed:{ name:'限制结算速度', intro:'在动画结算完成前不执行下一步操作,开启后游戏操作的间隔更长但画面更浏畅,在游戏较卡时建议开启', init:true }, enable_vibrate:{ name:'开启震动', intro:'回合开始时使手机震动', init:false }, right_click:{ name:'右键操作', init:'pause', intro:'在空白区域点击右键时的操作', unfrequent:true, item:{ pause:'暂停', shortcut:'工具', config:'选项', auto:'托管', }, onclick:function(item){ if(get.is.nomenu('right_click',item)) return false; game.saveConfig('right_click',item); } }, longpress_info:{ name:'长按显示信息', init:true, unfrequent:true, restart:true, intro:'长按后弹出菜单', }, right_info:{ name:'右键显示信息', init:true, unfrequent:true, restart:true, intro:'右键点击后弹出菜单', }, hover_all:{ name:'悬停显示信息', init:true, unfrequent:true, restart:true, intro:'悬停后弹出菜单', }, hover_handcard:{ name:'悬停手牌显示信息', init:true, unfrequent:true, intro:'悬停手牌后弹出菜单', }, hoveration:{ name:'悬停菜单弹出时间', unfrequent:true, intro:'鼠标移至目标到弹出菜单的时间间隔', init:'1000', item:{ '500':'0.5秒', '700':'0.7秒', '1000':'1秒', '1500':'1.5秒', '2500':'2.5秒', } }, doubleclick_intro:{ name:'双击显示武将资料', init:true, unfrequent:true, intro:'双击武将头像后显示其资料卡', }, video:{ name:'保存录像', init:'20', intro:'游戏结束后保存录像在最大条数,超过后将从最早的录像开始删除(已收藏的录像不计入条数)', item:{ '0':'关闭', '5':'五局', '10':'十局', '20':'二十局', '50':'五十局', '10000':'无限', }, unfrequent:true, }, max_loadtime:{ name:'最长载入时间', intro:'设置游戏从启动到完成载入所需的最长时间,超过此时间未完成载入会报错,若设备较慢或安装了较多扩展可适当延长此时间', init:'5000', unfrequent:true, item:{ 5000:'5秒', 10000:'10秒', 20000:'20秒', 60000:'60秒' }, onclick:function(item){ game.saveConfig('max_loadtime',item); if(item=='5000'){ localStorage.removeItem(lib.configprefix+'loadtime'); } else{ localStorage.setItem(lib.configprefix+'loadtime',item); } } }, mousewheel:{ name:'滚轮控制手牌', init:true, unfrequent:true, intro:'开启后滚轮可使手牌横向滚动,在mac等可横向滚动的设备上建议关闭', onclick:function(bool){ game.saveConfig('mousewheel',bool); if(lib.config.touchscreen) return; if(lib.config.mousewheel){ ui.handcards1Container.onmousewheel=ui.click.mousewheel; ui.handcards2Container.onmousewheel=ui.click.mousewheel; } else{ ui.handcards1Container.onmousewheel=null; ui.handcards2Container.onmousewheel=null; } } }, auto_check_update:{ name:'自动检查游戏更新', intro:'进入游戏时检查更新', init:false, unfrequent:true }, lucky_star:{ name:'幸运星模式', intro:'在涉及随机数等的技能中,必定得到效果最好的结果。(联机模式无效)', init:false, unfrequent:true }, dev:{ name:'开发者模式', intro:'开启后可使用浏览器控制台控制游戏,同时可更新到开发版', init:false, onclick:function(bool){ game.saveConfig('dev',bool); if(_status.connectMode) return; if(bool){ lib.cheat.i(); } else{ delete window.cheat; delete window.game; delete window.ui; delete window.get; delete window.ai; delete window.lib; delete window._status; } }, unfrequent:true, }, fuck_sojson:{ name:'检测加密扩展', init:false, }, errstop:{ name:'出错时停止游戏', init:false, unfrequent:true }, update_link:{ name:'更新地址', init:'coding', unfrequent:true, item:{ coding:'FastGit', github:'GitHub', }, onclick:function(item){ game.saveConfig('update_link',item); lib.updateURL=lib.updateURLS[item]||lib.updateURLS.coding; }, }, extension_source:{ name:'获取扩展地址', init:'GitHub Proxy', unfrequent:true, item:{}, intro:()=>`获取在线扩展时的地址。当前地址:${document.createElement('br').outerHTML}${lib.config.extension_sources[lib.config.extension_source]}` }, extension_create:{ name:'添加获取扩展地址', clear:true, unfrequent:true, onclick:function(){ game.prompt('请输入地址名称',function(str){ if(str){ var map=lib.config.extension_sources; game.prompt('请输入'+str+'的地址',function(str2){ if(str2){ delete map[str]; map[str]=str2; game.saveConfig('extension_sources',map); game.saveConfig('extension_source',str); var nodexx=ui.extension_source; nodexx.updateInner(); var nodeyy=nodexx._link.menu; var nodezz=nodexx._link.config; for(var i=0;i
    '); } }, onclick:function(theme){ game.saveConfig('theme',theme); ui.arena.hide(); lib.init.background(); if(lib.config.autostyle){ if(theme=='simple'){ lib.configMenu.appearence.config.player_border.onclick('slim'); } else{ lib.configMenu.appearence.config.player_border.onclick('normal'); } } setTimeout(function(){ var theme=ui.css.theme; ui.css.theme=lib.init.css(lib.assetURL+'theme/'+lib.config.theme,'style'); theme.remove(); setTimeout(function(){ui.arena.show();},100); },500); } }, layout:{ name:'布局', init:'mobile', item:{ //default:'旧版', newlayout:'对称', mobile:'默认', long:'宽屏', long2:'手杀', nova:'新版' }, visualMenu:function(node,link){ node.className='button character themebutton '+lib.config.theme; if(!node.created){ node.created=true; node.style.overflow='hidden'; node.firstChild.style.display='none'; // node.firstChild.classList.add('shadowed'); // node.firstChild.style.width='16px'; // node.firstChild.style.height='auto'; // node.firstChild.style.padding='2px'; // node.firstChild.style.textAlign='center'; var me=ui.create.div(node); me.style.top='auto'; if(link=='default'||link=='newlayout'){ me.style.width='calc(100% - 6px)'; me.style.left='3px'; me.style.bottom='3px'; me.style.height='25px'; if(link=='newlayout'){ me.style.height='23px'; me.style.bottom='4px'; } } else if(link=='long2'||link=='nova'){ me.style.display='none'; } else{ me.style.width='120%'; me.style.left='-10%'; me.style.bottom='0'; me.style.height='22px'; } me.style.borderRadius='2px'; var list=['re_caocao','re_liubei','sp_zhangjiao','sunquan']; for(var i=0;i<4;i++){ var player=ui.create.div('.fakeplayer',node); ui.create.div('.avatar',player).setBackground(list.randomRemove(),'character'); player.style.borderRadius='2px'; if(i!=3){ player.style.top='auto'; } if(link=='default'){ player.style.height='19px'; player.style.width='38px'; player.classList.add('oldlayout') } else if(link=='mobile'||link=='newlayout'){ player.style.width='24px'; player.style.height='29px'; } else if(link=='nova') { player.style.width='20px'; player.style.height='24px'; } else{ player.style.width='20px'; player.style.height='34px'; } if(i==1){ player.style.left='3px'; } if(i==2){ player.style.left='auto'; player.style.right='3px'; } if(i==3){ player.style.top='3px'; } if(link=='default'){ if(i==0){ player.style.bottom='6px'; } if(i==0||i==3){ player.style.left='calc(50% - 18px)'; } if(i==1||i==2){ player.style.bottom='36px'; } } else if(link=='newlayout'){ if(i==0){ player.style.bottom='1px'; } if(i==0||i==3){ player.style.left='calc(50% - 12px)'; } if(i==1||i==2){ player.style.bottom='32px'; } } else if(link=='mobile'){ if(i==0||i==3){ player.style.left='calc(50% - 12px)'; } if(i==1||i==2){ player.style.bottom='30px'; } } else if(link=='long'){ if(i==0||i==3){ player.style.left='calc(50% - 10px)'; } if(i==1||i==2){ player.style.bottom='45px'; } } else if(link=='long2'){ if(i==0){ player.style.bottom='2px'; player.style.left='3px'; } if(i==3){ player.style.left='calc(50% - 10px)'; } if(i==1||i==2){ player.style.bottom='45px'; } } else if(link=='nova'){ if(i==0){ player.style.bottom='2px'; player.style.left='3px'; } if(i==3){ player.style.left='calc(50% - 10px)'; } if(i==1||i==2){ player.style.left='3px'; player.style.bottom=(i*30)+'px'; } } if(i==0&&(link=='mobile'||link=='long')){ player.classList.add('me'); player.style.borderRadius='0px'; player.style.width='25px'; player.style.height='25px'; player.style.bottom='-3px'; player.style.left='-3px'; } } } }, onclick:function(layout){ if(lib.layoutfixed.contains(lib.config.mode)){ game.saveConfig('layout',layout); } else{ lib.init.layout(layout); } } }, splash_style:{ name:'启动页', item:{ style1:'样式一', style2:'样式二', }, visualMenu:(node,link)=>{ node.className='button character'; node.style.width='200px'; node.style.height=`${node.offsetWidth*1080/2400}px`; node.style.display='flex'; node.style.flexDirection='column'; node.style.alignItems='center'; node.style.backgroundSize='100% 100%'; node.setBackgroundImage(`image/splash/${link}.jpg`); } }, // fewplayer:{ // name:'启用人数', // intro:'设置启用新版布局的最小人数(不足时切换至默认布局)', // init:'3', // // unfrequent:true, // item:{ // '2':'两人', // '3':'三人', // '4':'四人', // '5':'五人', // '6':'六人', // '7':'七人', // '8':'八人', // }, // onclick:function(item){ // game.saveConfig('fewplayer',item); // if(ui.arena) ui.arena.setNumber(ui.arena.dataset.number); // } // }, player_height:{ name:'角色高度', init:'long', // unfrequent:true, item:{ short:'矮', default:'中', long:'高', }, onclick:function(item){ game.saveConfig('player_height',item); ui.arena.dataset.player_height=item; } }, player_height_nova:{ name:'角色高度', init:'short', item:{ // auto:'自动', short:'矮', default:'中', long:'高', }, onclick:function(item){ game.saveConfig('player_height_nova',item); // if(item=='auto'){ // if(parseInt(ui.arena.dataset.number)>=7){ // ui.arena.dataset.player_height_nova='short'; // } // else{ // ui.arena.dataset.player_height_nova='default'; // } // } // else{ ui.arena.dataset.player_height_nova=item; // } } }, // background_color_music:{ // name:'背景色', // init:'black', // item:{ // blue:'蓝色', // black:'黑色', // }, // onclick:function(color){ // game.saveConfig('background_color_music',color); // document.body.dataset.background_color_music=color; // } // }, // background_color_wood:{ // name:'背景色', // init:'blue', // item:{ // blue:'蓝色', // black:'黑色', // }, // onclick:function(color){ // game.saveConfig('background_color_wood',color); // document.body.dataset.background_color_wood=color; // } // }, // theme_color_music:{ // name:'主题色', // init:'black', // item:{ // blue:'蓝色', // black:'黑色', // }, // onclick:function(color){ // game.saveConfig('theme_color_music',color); // document.body.dataset.theme_color_music=color; // } // }, ui_zoom:{ name:'界面缩放', unfrequent:true, init:'normal', item:{ esmall:'80%', vsmall:'90%', small:'95%', normal:'100%', big:'105%', vbig:'110%', ebig:'120%', eebig:'150%', eeebig:'180%', eeeebig:'200%', }, onclick:function(zoom){ game.saveConfig('ui_zoom',zoom); switch(zoom){ case 'esmall':zoom=0.8;break; case 'vsmall':zoom=0.9;break; case 'small':zoom=0.93;break; case 'big':zoom=1.05;break; case 'vbig':zoom=1.1;break; case 'ebig':zoom=1.2;break; case 'eebig':zoom=1.5;break; case 'eeebig':zoom=1.8;break; case 'eeeebig':zoom=2;break; default:zoom=1; } game.documentZoom=game.deviceZoom*zoom; ui.updatez(); if (Array.isArray(lib.onresize)) { lib.onresize.forEach(fun => { if (typeof fun == 'function') fun(); }); } } }, image_background:{ name:'游戏背景', init:'default', item:{}, visualBar:function(node,item,create){ if(node.created){ node.lastChild.classList.remove('active'); return; } node.created=true; ui.create.filediv('.menubutton','添加背景',node,function(file){ if(file){ var name=file.name; if(name.includes('.')){ name=name.slice(0,name.indexOf('.')); } var link=(game.writeFile?'cdv_':'custom_')+name; if(item[link]){ for(var i=1;i<1000;i++){ if(!item[link+'_'+i]){ link=link+'_'+i;break; } } } item[link]=name; var callback=function(){ create(link,node.parentNode.defaultNode); node.parentNode.updateBr(); lib.config.customBackgroundPack.add(link); game.saveConfig('customBackgroundPack',lib.config.customBackgroundPack); }; if(game.writeFile){ game.writeFile(file,'image/background',link+'.jpg',callback); } else{ game.putDB('image',link,file,callback); } if(node.lastChild.classList.contains('active')){ editbg.call(node.lastChild); } } }).inputNode.accept='image/*'; var editbg=function(){ this.classList.toggle('active'); var page=this.parentNode.parentNode; for(var i=0;i4){ node.classList.add('hideadd'); button.classList.remove('transparent'); delete node.currentDB; } }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); }); } }).inputNode.accept='image/*'; deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){ if(confirm('确定删除自定义图片?(此操作不可撤销)')){ game.deleteDB('image','hp_style1'); game.deleteDB('image','hp_style2'); game.deleteDB('image','hp_style3'); game.deleteDB('image','hp_style4'); for(var i=0;idiv:not(.lost){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','hp_style2',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet2){ ui.css.hp_stylesheet2.remove(); } ui.css.hp_stylesheet2=lib.init.sheet('.hp:not(.text):not(.actcount)[data-condition="mid"]>div:not(.lost){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','hp_style3',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet3){ ui.css.hp_stylesheet3.remove(); } ui.css.hp_stylesheet3=lib.init.sheet('.hp:not(.text):not(.actcount)[data-condition="low"]>div:not(.lost){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','hp_style4',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet4){ ui.css.hp_stylesheet4.remove(); } ui.css.hp_stylesheet4=lib.init.sheet('.hp:not(.text):not(.actcount)>.lost{background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } }, unfrequent:true, }, player_style:{ name:'角色背景', init:'default', intro:'设置角色的背景图片', item:{ wood:'木纹', music:'音乐', simple:'简约', custom:'自定', default:'默认', }, visualBar:function(node,item,create,switcher){ if(node.created){ return; } var button; for(var i=0;i.framebg{display:block;background-image:url("'+fileLoadedEvent.target.result+'")}',0); ui.css.border_stylesheet.sheet.insertRule('.player>.count{z-index: 3 !important;border-radius: 2px !important;text-align: center !important;}',0); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } else if(layout!='default'&&layout!='auto'){ ui.css.border_stylesheet=lib.init.sheet(); if(layout.startsWith('dragon_')){ layout=layout.slice(7); ui.arena.dataset.framedecoration=layout; } else{ ui.arena.dataset.framedecoration=''; } ui.css.border_stylesheet.sheet.insertRule('#window .player>.framebg,#window #arena.long.mobile:not(.fewplayer) .player[data-position="0"]>.framebg{display:block;background-image:url("'+lib.assetURL+'theme/style/player/'+layout+'1.png")}',0); ui.css.border_stylesheet.sheet.insertRule('#window #arena.long:not(.fewplayer) .player>.framebg, #arena.oldlayout .player>.framebg{background-image:url("'+lib.assetURL+'theme/style/player/'+layout+'3.png")}',0); ui.css.border_stylesheet.sheet.insertRule('.player>.count{z-index: 3 !important;border-radius: 2px !important;text-align: center !important;}',0); } }, unfrequent:true, }, autoborder_count:{ name:'边框升级方式', intro:'击杀 每击杀一人,边框提升两级
    伤害 每造成两点伤害,边框提升一级
    混合 击杀量决定边框颜色,伤害量决定边框装饰', init:'kill', item:{ kill:'击杀', damage:'伤害', mix:'混合', }, unfrequent:true, }, autoborder_start:{ name:'基础边框颜色', init:'bronze', item:{ bronze:'铜', silver:'银', gold:'金' }, unfrequent:true }, player_border:{ name:'边框宽度', init:'normal', intro:'设置角色的边框宽度', unfrequent:true, item:{ slim:'细', narrow:'窄', normal:'中', wide:'宽' }, onclick:function(item){ game.saveConfig('player_border',item); if(item!='wide'||game.layout=='long'||game.layout=='long2'){ ui.arena.classList.add('slim_player'); } else{ ui.arena.classList.remove('slim_player'); } if(item=='slim'){ ui.arena.classList.add('uslim_player'); } else{ ui.arena.classList.remove('uslim_player'); } if(item=='narrow'){ ui.arena.classList.add('mslim_player'); } else{ ui.arena.classList.remove('mslim_player'); } if(item=='normal'&&lib.config.mode!='brawl'&&(game.layout=='long'||game.layout=='long2')){ ui.arena.classList.add('lslim_player'); } else{ ui.arena.classList.remove('lslim_player'); } ui.window.dataset.player_border=item; } }, menu_style:{ name:'菜单背景', init:'default', item:{ wood:'木纹', music:'音乐', simple:'简约', custom:'自定', default:'默认', }, visualBar:function(node,item,create,switcher){ if(node.created){ return; } var button; for(var i=0;i.dialog.popped,html .menu,html .menubg{background-image:url("'+fileLoadedEvent.target.result+'");background-size:cover}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } else if(layout!='default'){ var str=''; switch(layout){ case 'wood':str='url("'+lib.assetURL+'theme/woodden/wood2.png")';break; case 'music':str='linear-gradient(#4b4b4b, #464646);color:white;text-shadow:black 0 0 2px';break; case 'simple':str='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4));color:white;text-shadow:black 0 0 2px';break; } ui.css.menu_stylesheet=lib.init.sheet('html #window>.dialog.popped,html .menu,html .menubg{background-image:'+str+'}'); } }, unfrequent:true, }, control_style:{ name:'按钮背景', init:'default', item:{ wood:'木纹', music:'音乐', simple:'简约', custom:'自定', default:'默认', }, visualBar:function(node,item,create,switcher){ if(node.created){ return; } var button; for(var i=0;idiv>div{background-image:url("'+fileLoadedEvent.target.result+'")}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } else if(layout!='default'){ var str=''; switch(layout){ case 'wood':str='url("'+lib.assetURL+'theme/woodden/wood.jpg")';break; case 'music':str='linear-gradient(#4b4b4b, #464646);color:white;text-shadow:black 0 0 2px';break; case 'simple':str='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4));color:white;text-shadow:black 0 0 2px';break; } if(layout=='wood'){ ui.css.control_stylesheet=lib.init.sheet('#window .control,#window .menubutton,#window #system>div>div,#window #system>div>.pressdown2{background-image:'+str+'}'); } else{ ui.css.control_stylesheet=lib.init.sheet('#window .control,.menubutton:not(.active):not(.highlight):not(.red):not(.blue),#window #system>div>div{background-image:'+str+'}'); } } }, unfrequent:true, }, custom_button:{ name:'自定义按钮高度', init:false, unfrequent:true, onclick:function(bool){ if(bool!=='skip'){ game.saveConfig('custom_button',bool); } if(ui.css.buttonsheet){ ui.css.buttonsheet.remove(); } if(lib.config.custom_button){ var cbnum1=6+(parseInt(lib.config.custom_button_system_top)||0); var cbnum2=6+(parseInt(lib.config.custom_button_system_bottom)||0); var cbnum3=3+(parseInt(lib.config.custom_button_control_top)||0); var cbnum4=3+(parseInt(lib.config.custom_button_control_bottom)||0); var cbnum5=2; var cbnum6=2; if(cbnum3<0){ cbnum5+=cbnum3; cbnum3=0; } if(cbnum4<0){ cbnum6+=cbnum4; cbnum4=0; } ui.css.buttonsheet=lib.init.sheet( '#system>div>div, .caption>div>.tdnode{padding-top:'+cbnum1+'px !important;padding-bottom:'+cbnum2+'px !important}', '#control>.control>div{padding-top:'+cbnum3+'px;padding-bottom:'+cbnum4+'px}', '#control>.control{padding-top:'+cbnum5+'px;padding-bottom:'+cbnum6+'px}' ); } } }, custom_button_system_top:{ name:'菜单上部高度', init:'0x', item:{ '-5x':'-5px', '-4x':'-4px', '-3x':'-3px', '-2x':'-2px', '-1x':'-1px', '0x':'默认', '1x':'1px', '2x':'2px', '3x':'3px', '4x':'4px', '5x':'5px', }, unfrequent:true, onclick:function(item){ game.saveConfig('custom_button_system_top',item); lib.configMenu.appearence.config.custom_button.onclick('skip'); } }, custom_button_system_bottom:{ name:'菜单下部高度', init:'0x', item:{ '-5x':'-5px', '-4x':'-4px', '-3x':'-3px', '-2x':'-2px', '-1x':'-1px', '0x':'默认', '1x':'1px', '2x':'2px', '3x':'3px', '4x':'4px', '5x':'5px', }, unfrequent:true, onclick:function(item){ game.saveConfig('custom_button_system_bottom',item); lib.configMenu.appearence.config.custom_button.onclick('skip'); } }, custom_button_control_top:{ name:'技能上部高度', init:'0x', item:{ '-5x':'-5px', '-4x':'-4px', '-3x':'-3px', '-2x':'-2px', '-1x':'-1px', '0x':'默认', '1x':'1px', '2x':'2px', '3x':'3px', '4x':'4px', '5x':'5px', }, unfrequent:true, onclick:function(item){ game.saveConfig('custom_button_control_top',item); lib.configMenu.appearence.config.custom_button.onclick('skip'); } }, custom_button_control_bottom:{ name:'技能下部高度', init:'0x', item:{ '-5x':'-5px', '-4x':'-4px', '-3x':'-3px', '-2x':'-2px', '-1x':'-1px', '0x':'默认', '1x':'1px', '2x':'2px', '3x':'3px', '4x':'4px', '5x':'5px', }, unfrequent:true, onclick:function(item){ game.saveConfig('custom_button_control_bottom',item); lib.configMenu.appearence.config.custom_button.onclick('skip'); } }, radius_size:{ name:'圆角大小', init:'default', item:{ off:'关闭', reduce:'减小', default:'默认', increase:'增大', }, unfrequent:true, onclick:function(item){ game.saveConfig('radius_size',item); ui.window.dataset.radius_size=item; } }, glow_phase:{ name:'当前回合角色高亮', unfrequent:true, init:'yellow', intro:'设置当前回合角色的边框颜色', item:{ none:'无', yellow:'黄色', green:'绿色', purple:'紫色', }, onclick:function(bool){ game.saveConfig('glow_phase',bool); lib.init.cssstyles(); } }, fold_card:{ name:'折叠手牌', init:true, unfrequent:true, }, fold_mode:{ name:'折叠模式菜单', intro:'关闭后模式菜单中“更多”内的项目将直接展开', init:true, unfrequent:true, }, seperate_control:{ name:'分离选项条', init:true, unfrequent:true, intro:'开启后玩家在进行选择时不同的选项将分开,而不是连在一起', }, blur_ui:{ name:'模糊效果', intro:'在暂停或打开菜单时开启模糊效果', init:false, unfrequent:true, onclick:function(bool){ game.saveConfig('blur_ui',bool); if(bool){ ui.window.classList.add('blur_ui'); } else{ ui.window.classList.remove('blur_ui'); } } }, glass_ui:{ name:'玻璃主题', intro:'为游戏主题打开玻璃效果(手机暂不支持)', init:false, unfrequent:true, onclick:function(bool){ game.saveConfig('glass_ui',bool); if(bool){ ui.window.classList.add('glass_ui'); } else{ ui.window.classList.remove('glass_ui'); } } }, damage_shake:{ name:'伤害抖动', intro:'角色受到伤害时的抖动效果', init:true, unfrequent:true, }, button_press:{ name:'按钮效果', intro:'选项条被按下时将有按下效果', init:true, unfrequent:true, }, jiu_effect:{ name:'喝酒效果', init:true, unfrequent:true, }, animation:{ name:'游戏特效', intro:'开启后出现属性伤害、回复体力等情况时会显示动画', init:false, unfrequent:true, }, skill_animation_type:{ name:'技能特效', intro:'开启后觉醒技、限定技将显示全屏文字', init:'default', unfrequent:true, item:{ default:'默认', old:'旧版', off:'关闭' } }, die_move:{ name:'阵亡效果', intro:'阵亡后武将的显示效果', init:'flip', unfrequent:true, item:{ off:'关闭', move:'移动', flip:'翻面', } }, target_shake:{ name:'目标效果', intro:'一名玩家成为卡牌或技能的目标时的显示效果', init:'off', item:{ off:'关闭', zoom:'缩放', shake:'抖动', }, unfrequent:true, onclick:function(bool){ game.saveConfig('target_shake',bool); ui.arena.dataset.target_shake=bool; } }, turned_style:{ name:'翻面文字', intro:'角色被翻面时显示“翻面”', init:true, unfrequent:true, onclick:function(bool){ game.saveConfig('turned_style',bool); if(bool){ ui.arena.classList.remove('hide_turned'); } else{ ui.arena.classList.add('hide_turned'); } } }, link_style2:{ name:'横置样式', intro:'设置角色被横置时的样式', init:'chain', unfrequent:true, item:{ chain:'铁索', rotate:'横置', mark:'标记' }, onclick:function(style){ var list=[]; for(var i=0;i{ node.classList.add('button','character'); const style=node.style; style.alignItems='center'; style.animation='background-position-left-center-right-center-left-center 15s ease infinite'; style.background='linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB)'; style.backgroundSize='400% 400%'; style.display='flex'; style.height='60px'; style.justifyContent='center'; style.width='180px'; const firstChild=node.firstChild; firstChild.removeAttribute('class'); firstChild.style.position='initial'; if(link=='doNotShow') return; const ruby=document.createElement('ruby'); ruby.textContent=name; const rt=document.createElement('rt'); rt.style.fontSize='smaller'; if(link=='showPinyin2'||link=='showCodeIdentifier2'){ rt.textContent=link=='showCodeIdentifier2'?'['+link+']':'['+get.pinyin(name)+']'; ruby.appendChild(rt); }else{ const leftParenthesisRP=document.createElement('rp'); leftParenthesisRP.textContent='('; ruby.appendChild(leftParenthesisRP); rt.textContent=link=='showCodeIdentifier'?link:get.pinyin(name).join(' '); ruby.appendChild(rt); const rightParenthesisRP=document.createElement('rp'); rightParenthesisRP.textContent=')'; ruby.appendChild(rightParenthesisRP); } firstChild.innerHTML=ruby.outerHTML; } }, show_skillnamepinyin:{ name:'显示技能名注解', intro:'在武将资料卡显示技能名注解', get init(){ return lib.configMenu.view.config.show_characternamepinyin.init; }, get unfrequent(){ return lib.configMenu.view.config.show_characternamepinyin.unfrequent; }, get item(){ return lib.configMenu.view.config.show_characternamepinyin.item; }, get visualMenu(){ return lib.configMenu.view.config.show_characternamepinyin.visualMenu; } } } }, audio:{ name:'音效', config:{ update:function(config,map){ if(lib.config.background_music=='music_custom'&&(lib.device||lib.node)){ map.import_music.show(); } else{ map.import_music.hide(); } map.clear_background_music[get.is.object(lib.config.customBackgroundMusic)?'show':'hide'](); ui.background_music_setting=map.background_music; map.background_music._link.config.updatex.call(map.background_music,[]); }, background_music:{ updatex:function(){ this.lastChild.innerHTML=this._link.config.item[lib.config.background_music]; var menu=this._link.menu; for(var i=0;i'+ ''+ '', clear:true, }, background_audio:{ name:'游戏音效', init:true, }, background_speak:{ name:'人物配音', init:true, }, equip_audio:{ name:'装备配音', init:false, }, repeat_audio:{ name:'播放重复语音', init:false, }, volumn_audio:{ name:'音效音量', init:8, item:{ '0':'〇', '1':'一', '2':'二', '3':'三', '4':'四', '5':'五', '6':'六', '7':'七', '8':'八', }, onclick:function(volume){ game.saveConfig('volumn_audio',parseInt(volume)); } }, volumn_background:{ name:'音乐音量', init:8, item:{ '0':'〇', '1':'一', '2':'二', '3':'三', '4':'四', '5':'五', '6':'六', '7':'七', '8':'八', }, onclick:function(volume){ game.saveConfig('volumn_background',parseInt(volume)); ui.backgroundMusic.volume=volume/8; } }, clear_background_music:{ name:'清除自定义背景音乐', clear:true, onclick:function(){ if(confirm('是否清除已导入的所有自定义背景音乐?(该操作不可撤销!)')){ for(var i in lib.config.customBackgroundMusic){ lib.config.all.background_music.remove(i); if(i.startsWith('cdv_')){ game.removeFile('audio/background/'+i+'.mp3'); } else{ game.deleteDB('audio',i); } } lib.config.customBackgroundMusic=null; game.saveConfig('customBackgroundMusic',null); game.saveConfig('background_music','music_off'); if(!_status._aozhan) game.playBackgroundMusic(); } }, }, } }, skill:{ name:'技能', config:{ update:function(config,map){ for(var i in map){ if(map[i]._link.config.type=='autoskill'){ if(!lib.config.autoskilllist.contains(i)){ map[i].classList.add('on'); } else{ map[i].classList.remove('on'); } } else if(map[i]._link.config.type=='banskill'){ if(!lib.config.forbidlist.contains(i)){ map[i].classList.add('on'); } else{ map[i].classList.remove('on'); } } } } } }, others:{ name:'其它', config:{ // reset_database:{ // name:'重置游戏', // onclick:function(){ // var node=this; // if(node._clearing){ // if(indexedDB) indexedDB.deleteDatabase(lib.configprefix+'data'); // game.reload(); // return; // } // node._clearing=true; // node.innerHTML='单击以确认 (3)'; // setTimeout(function(){ // node.innerHTML='单击以确认 (2)'; // setTimeout(function(){ // node.innerHTML='单击以确认 (1)'; // setTimeout(function(){ // node.innerHTML='重置游戏录像'; // delete node._clearing; // },1000); // },1000); // },1000); // }, // clear:true // }, reset_game:{ name:'重置游戏设置', onclick:function(){ var node=this; if(node._clearing){ var noname_inited=localStorage.getItem('noname_inited'); var onlineKey=localStorage.getItem(lib.configprefix+'key'); localStorage.clear(); if(noname_inited){ localStorage.setItem('noname_inited',noname_inited); } if(onlineKey){ localStorage.setItem(lib.configprefix+'key',onlineKey); } game.deleteDB('config'); game.deleteDB('data'); game.reload(); return; } node._clearing=true; node.firstChild.innerHTML='单击以确认 (3)'; setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (2)'; setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (1)'; setTimeout(function(){ node.firstChild.innerHTML='重置游戏设置'; delete node._clearing; },1000); },1000); },1000); }, clear:true }, reset_hiddenpack:{ name:'重置隐藏内容', onclick:function(){ if(this.firstChild.innerHTML!='已重置'){ this.firstChild.innerHTML='已重置' game.saveConfig('hiddenModePack',[]); game.saveConfig('hiddenCharacterPack',[]); game.saveConfig('hiddenCardPack',[]); game.saveConfig('hiddenPlayPack',[]); game.saveConfig('hiddenBackgroundPack',[]); var that=this; setTimeout(function(){ that.firstChild.innerHTML='重置隐藏内容'; setTimeout(function(){ if(confirm('是否重新启动使改变生效?')){ game.reload(); } }); },500); } }, clear:true }, reset_tutorial:{ name:'重置新手向导', onclick:function(){ if(this.firstChild.innerHTML!='已重置'){ this.firstChild.innerHTML='已重置' game.saveConfig('new_tutorial',false); game.saveConfig('prompt_hidebg'); game.saveConfig('prompt_hidepack'); var that=this; setTimeout(function(){ that.firstChild.innerHTML='重置新手向导'; },500); } }, clear:true }, import_data:{ name:'导入游戏设置', onclick:function(){ ui.import_data_button.classList.toggle('hidden'); }, clear:true }, import_data_button:{ name:'
    '+ ''+ '
    ', clear:true, }, export_data:{ name:'导出游戏设置', onclick:function(){ var data; var export_data=function(data){ game.export(lib.init.encode(JSON.stringify(data)),'无名杀 - 数据 - '+(new Date()).toLocaleString()); } if(!lib.db){ data={}; for(var i in localStorage){ if(i.startsWith(lib.configprefix)){ data[i]=localStorage[i]; } } export_data(data); } else{ game.getDB('config',null,function(data1){ game.getDB('data',null,function(data2){ export_data({ config:data1, data:data2 }); }); }); } }, clear:true }, redownload_game:{ name:'重新下载游戏', onclick:function(){ var node=this; if(node._clearing){ localStorage.removeItem('noname_inited'); game.reload(); return; } node._clearing=true; node.firstChild.innerHTML='单击以确认 (3)'; setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (2)'; setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (1)'; setTimeout(function(){ node.firstChild.innerHTML='重新下载游戏'; delete node._clearing; },1000); },1000); },1000); }, clear:true }, update:function(config,map){ if(lib.device||lib.node){ map.redownload_game.show(); } else{ map.redownload_game.hide(); } } // trim_game:{ // name:'隐藏非官方扩展包', // onclick:function(){ // if(this.innerHTML!='已隐藏'){ // this.innerHTML='已隐藏'; // var pack=lib.config.all.cards.slice(0); // if(Array.isArray(lib.config.hiddenCardPack)){ // for(var i=0;igame.players.length*num&&game.showIdentity){ _status.identityShown=true; game.showIdentity(false); } }, intro:'游戏进行若干轮将自动显示所有角色的身份', }, auto_mark_identity:{ name:'自动标记身份', init:true, intro:'根据角色的出牌行为自动标记可能的身份', }, // ban_weak:{ // name:'屏蔽弱将', // init:true, // restart:true, // }, // ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true, // }, enhance_zhu:{ name:'加强主公', init:false, restart:true, intro:'为主公增加一个额外技能' }, free_choose:{ name:'自由选将', init:true, onclick:function(bool){ game.saveConfig('free_choose',bool,this._link.config.mode); if(get.mode()!=this._link.config.mode||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat2&&get.config('free_choose')) ui.create.cheat2(); else if(ui.cheat2&&!get.config('free_choose')){ ui.cheat2.close(); delete ui.cheat2; } } }, change_identity:{ name:'自由选择身份和座位', init:true, onclick:function(bool){ game.saveConfig('change_identity',bool,this._link.config.mode); if(get.mode()!='identity'||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; var dialog; if(ui.cheat2&&ui.cheat2.backup) dialog=ui.cheat2.backup; else dialog=_status.event.dialog; if(!_status.brawl||!_status.brawl.noAddSetting){ if(!dialog.querySelector('table')&&get.config('change_identity')) _status.event.getParent().addSetting(dialog); else _status.event.getParent().removeSetting(dialog); } ui.update(); } }, change_choice:{ name:'开启换将卡', init:true, onclick:function(bool){ game.saveConfig('change_choice',bool,this._link.config.mode); if(get.mode()!='identity'||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat&&get.config('change_choice')) ui.create.cheat(); else if(ui.cheat&&!get.config('change_choice')){ ui.cheat.close(); delete ui.cheat; } } }, change_card:{ name:'开启手气卡', init:'disabled', item:{ disabled:'禁用', once:'一次', twice:'两次', unlimited:'无限', }, }, round_one_use_fury:{ name:'开启首轮强化卡牌', init:false, frequent:false, restart:true, intro:'谋攻篇规则为第二轮开始才可使用怒气强化卡牌,开启此选项从游戏开始即可强化卡牌。' }, nei_auto_mark_camouflage:{ name:'内奸自动标记伪装反贼', intro:'玩家内奸在游戏开始洞察结束后,自动将被洞察角色标记为反贼。', init:false, unfrequent:true, }, continue_game:{ name:'显示再战', init:false, onclick:function(bool){ game.saveConfig('continue_game',bool,this._link.config.mode); if(get.config('continue_game')&&get.mode()=='identity'){ if(!ui.continue_game&&_status.over&&!_status.brawl&&!game.no_continue_game){ ui.continue_game=ui.create.control('再战',game.reloadCurrent); } } else if(ui.continue_game){ ui.continue_game.close(); delete ui.continue_game; } }, intro:'游戏结束后可选择用相同的武将再进行一局游戏' }, dierestart:{ name:'死亡后显示重来', init:true, onclick:function(bool){ game.saveConfig('dierestart',bool,this._link.config.mode); if(get.config('dierestart')&&get.mode()=='identity'){ if(!ui.restart&&game.me.isDead()&&!_status.connectMode){ ui.restart=ui.create.control('restart',game.reload); } } else if(ui.restart){ ui.restart.close(); delete ui.restart; } } }, revive:{ name:'死亡后显示复活', init:false, onclick:function(bool){ game.saveConfig('revive',bool,this._link.config.mode); if(get.config('revive')&&get.mode()=='identity'){ if(!ui.revive&&game.me.isDead()){ ui.revive=ui.create.control('revive',ui.click.dierevive); } } else if(ui.revive){ ui.revive.close(); delete ui.revive; } } }, ban_identity:{ name:'屏蔽身份', init:'off', item:{ off:'关闭', zhu:'主公', zhong:'忠臣', nei:'内奸', fan:'反贼', }, }, ban_identity2:{ name:'屏蔽身份2', init:'off', item:{ off:'关闭', zhu:'主公', zhong:'忠臣', nei:'内奸', fan:'反贼', }, }, ban_identity3:{ name:'屏蔽身份3', init:'off', item:{ off:'关闭', zhu:'主公', zhong:'忠臣', nei:'内奸', fan:'反贼', }, }, ai_strategy:{ name:'内奸策略', init:'ai_strategy_1', item:{ ai_strategy_1:'均衡', ai_strategy_2:'偏反', ai_strategy_3:'偏忠', ai_strategy_4:'酱油', ai_strategy_5:'天使', ai_strategy_6:'仇主', }, intro:'设置内奸对主忠反的态度' }, difficulty:{ name:'AI对人类态度', init:'normal', item:{ easy:'友好', normal:'一般', hard:'仇视', }, }, choice_zhu:{ name:'主公候选武将数', init:'3', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, limit_zhu:{ name:'常备主候选武将数', init:'group', restart:true, item:{ off:'不限制', group:'按势力筛选', '4':'四', '6':'六', '8':'八', }, }, choice_zhong:{ name:'忠臣候选武将数', init:'4', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, choice_nei:{ name:'内奸候选武将数', init:'5', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, choice_fan:{ name:'反贼候选武将数', init:'3', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, } }, guozhan:{ name:'国战', connect:{ connect_guozhan_mode:{ name:'游戏模式', init:'normal', item:{ normal:'势备', yingbian:'应变', old:'怀旧', }, frequent:true, restart:true, intro:'
  • 势备:默认模式,使用线下《君临天下·势备篇》的牌堆进行游戏。
  • 应变:使用OL的应变国战牌堆进行游戏。
  • 怀旧:使用传统国战的牌堆进行游戏。', }, connect_player_number:{ name:'游戏人数', init:'8', get item(){ return lib.mode.guozhan.config.player_number.item; }, frequent:true, restart:true, }, get connect_separatism(){ return lib.mode.guozhan.config.separatism; }, connect_initshow_draw:{ name:'首亮奖励', item:{ 'off':'关闭', 'draw':'摸牌', 'mark':'标记', }, init:'mark', frequent:true, intro:'第一个明置武将牌的角色可获得首亮奖励' }, connect_aozhan:{ name:'鏖战模式', init:true, intro:'若开启此选项,则将在游戏中引入“鏖战模式”的规则:
    当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。
    ◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。
    注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。', frequent:true, restart:true, }, connect_viewnext:{ name:'观看下家副将', init:false, intro:'若开启此选项,所有的玩家将在挑选武将后,分发起始手牌之前,分别观看自己下家的副将。', }, connect_zhulian:{ name:'珠联璧合', init:true, // frequent:true, intro:'主将和副将都明置后,若为特定组合,可获得【珠联璧合】标记' }, connect_junzhu:{ name:'替换君主', init:true, // frequent:true, restart:true, intro:'若开启此选项,玩家的第一个回合开始时,若其主武将牌有对应的君主武将牌,则其可以将此武将牌替换为对应的君主武将牌,然后重新调整体力上限。若玩家的体力上限因此增大,则玩家回复等量的体力。' }, connect_change_card:{ name:'启用手气卡', init:false, frequent:true, restart:true, }, // connect_ban_weak:{ // name:'屏蔽弱将', // init:false, // restart:true, // }, // connect_ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true, // }, }, config:{ update:function(config,map){ if(config.onlyguozhan){ map.junzhu.show(); } else{ map.junzhu.hide(); } ui.aozhan_bgm=map.aozhan_bgm; map.aozhan_bgm._link.config.updatex.call(map.aozhan_bgm,[]); }, guozhan_mode:{ name:'游戏模式', init:'normal', item:{ normal:'势备', yingbian:'应变', old:'怀旧', free:'自由', }, frequent:true, restart:true, intro:'
  • 势备:默认模式,使用线下《君临天下·势备篇》的牌堆进行游戏。
  • 应变:使用OL的应变国战牌堆进行游戏。
  • 怀旧:使用传统国战的牌堆进行游戏。
  • 自由:使用玩家的自定义牌堆进行游戏。', }, player_number:{ name:'游戏人数', init:'8', get item(){ const minimumNumberOfPlayers=2,maximumNumberOfPlayers=Math.max(_status.maximumNumberOfPlayers||12,minimumNumberOfPlayers),item={}; for(let playerNumber=minimumNumberOfPlayers;playerNumber<=maximumNumberOfPlayers;playerNumber++){ item[playerNumber]=`${get.cnNumber(playerNumber)}人`; } return item; }, frequent:true, restart:true, }, separatism:{ name:'群雄割据', init:false, frequent:true, restart:true, intro:'开放不同势力组合,以优先亮出的武将牌作为自己的势力,双势力武将则使用列表的第一个势力' }, initshow_draw:{ name:'首亮奖励', item:{ 'off':'关闭', 'draw':'摸牌', 'mark':'标记', }, init:'mark', frequent:true, intro:'第一个明置身份牌的角色可获得摸牌奖励' }, aozhan:{ name:'鏖战模式', init:true, frequent:true, restart:true, intro:'若开启此选项,则将在游戏中引入“鏖战模式”的规则:
    当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。
    ◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。
    注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。', }, viewnext:{ name:'观看下家副将', init:false, intro:'若开启此选项,所有的玩家将在挑选武将后,分发起始手牌之前,分别观看自己下家的副将。', }, aozhan_bgm:{ updatex:function(){ this.lastChild.innerHTML=this._link.config.item[lib.config.mode_config.guozhan.aozhan_bgm]; if(!Array.isArray(_status.aozhanBGMToRemove)) return; const menu=this._link.menu; for(let i=0;i1v1', }, restart:true, frequent:true, }, ladder:{ name:'天梯模式', init:true, frequent:true, restart:true }, ladder_monthly:{ name:'每月重置天梯', init:true, frequent:true, }, enable_all:{ name:'启用全部武将', init:false, frequent:true, restart:true, }, enable_all_cards_four:{ name:'启用全部卡牌', init:false, frequent:true, restart:true, }, enable_all_three:{ name:'启用全部武将', init:false, frequent:true, restart:true, }, enable_all_cards:{ name:'启用全部卡牌', init:false, frequent:true, restart:true, }, four_assign:{ name:'代替队友选将', init:false, restart:true, }, four_phaseswap:{ name:'代替队友行动', init:false, restart:true, }, two_assign:{ name:'代替队友选将', init:false, restart:true, }, two_phaseswap:{ name:'代替队友行动', init:false, restart:true, }, free_choose:{ name:'自由选将', init:true, frequent:true, onclick:function(bool){ game.saveConfig('free_choose',bool,this._link.config.mode); if(!ui.create.cheat2) return; if(get.mode()!=this._link.config.mode||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat2&&get.config('free_choose')) ui.create.cheat2(); else if(ui.cheat2&&!get.config('free_choose')){ ui.cheat2.close(); delete ui.cheat2; } } }, fouralign:{ name:'自由选择阵型', init:false }, change_identity:{ name:'自由选择座位', init:true, onclick:function(bool){ game.saveConfig('change_identity',bool,this._link.config.mode); if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(_status.mode=='four'){ if(get.config('four_assign')||get.config('four_phaseswap')) return; if(bool){ if(_status.event.parent.addSetting){ _status.event.parent.addSetting(); } } else{ var seats=_status.event.parent.seatsbutton; if(seats){ while(seats.length){ seats.shift().remove(); } delete _status.event.parent.seatsbutton; } } } else{ var dialog; if(ui.cheat2&&ui.cheat2.backup) dialog=ui.cheat2.backup; else dialog=_status.event.dialog; if(!_status.brawl||!_status.brawl.noAddSetting){ if(!dialog.querySelector('table')&&get.config('change_identity')) _status.event.getParent().addSetting(dialog); else _status.event.getParent().removeSetting(dialog); } ui.update(); } } }, change_choice:{ name:'开启换将卡', init:true, onclick:function(bool){ game.saveConfig('change_choice',bool,this._link.config.mode); if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat&&get.config('change_choice')) ui.create.cheat(); else if(ui.cheat&&!get.config('change_choice')){ ui.cheat.close(); delete ui.cheat; } }, frequent:true, }, double_character_jiange:{ name:'双将模式', init:false, frequent:true, }, replace_handcard_two:{ name:'四号位保护', init:true, frequent:true, intro:'最后行动的角色起始手牌+1' }, replace_character_two:{ name:'替补模式', init:false, frequent:true, intro:'每个额外选择一名武将,死亡后用该武将代替重新上场,替补武将用完时失败' }, expand_dialog:{ name:'默认展开选将框', intro:'选将框打开时直接显示全部武将(可能使游戏在开始时卡顿)', init:false, }, siguo_character:{ name:'专属武将出场率', init:'increase', item:{ increase:'大概率', normal:'默认概率', off:'不出现', }, frequent:true }, // ban_weak:{ // name:'屏蔽弱将', // init:true, // restart:true, // }, // ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true // }, ladder_reset:{ name:'重置天梯数据', onclick:function(){ var node=this; if(node._clearing){ game.save('ladder',{ current:900, top:900, month:(new Date()).getMonth() }); ui.ladder.innerHTML='卫士五'; clearTimeout(node._clearing); node.firstChild.innerHTML='重置天梯数据'; delete node._clearing; return; } node.firstChild.innerHTML='单击以确认 (3)'; node._clearing=setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (2)'; node._clearing=setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (1)'; node._clearing=setTimeout(function(){ node.firstChild.innerHTML='重置天梯数据'; delete node._clearing; },1000); },1000); },1000); }, clear:true, }, edit_character_three:{ name:'编辑统率将池', clear:true, onclick:function(){ if(get.mode()!='versus'){ alert('请进入对决模式,然后再编辑将池'); return; } var container=ui.create.div('.popup-container.editor'); var node=container; var map=get.config('character_three')||lib.choiceThree; var str='character=[\n '; for(var i=0;ilib.codeMirrorReady(node,editor)); lib.init.css(lib.assetURL+'layout/default','codemirror'); } else{ lib.codeMirrorReady(node,editor); } }; }, }, reset_character_three:{ name:'重置统率将池', intro:'将统率三军模式下的将池重置为默认将池', clear:true, onclick:function(){ if(confirm('该操作不可撤销!是否清除统率三军模式的自定义将池,并将其重置为默认将池?')){ game.saveConfig('character_three',null,'versus'); alert('将池已重置'); } }, }, edit_character_four:{ name:'编辑4v4将池', clear:true, onclick:function(){ if(get.mode()!='versus'){ alert('请进入对决模式,然后再编辑将池'); return; } var container=ui.create.div('.popup-container.editor'); var node=container; var map=get.config('character_four')||lib.choiceFour; var str='character=[\n '; for(var i=0;ilib.codeMirrorReady(node,editor)); lib.init.css(lib.assetURL+'layout/default','codemirror'); } else{ lib.codeMirrorReady(node,editor); } }; }, }, reset_character_four:{ name:'重置4v4将池', intro:'将4v4模式下的将池重置为默认将池', clear:true, onclick:function(){ if(confirm('该操作不可撤销!是否清除4v4模式的自定义将池,并将其重置为默认将池?')){ game.saveConfig('character_four',null,'versus'); alert('将池已重置'); } }, }, } }, connect:{ name:'联机', config:{ connect_nickname:{ name:'联机昵称', input:true, frequent:true, }, connect_avatar:{ name:'联机头像', init:'caocao', item:{}, frequent:true, onclick:function(item){ game.saveConfig('connect_avatar',item); game.saveConfig('connect_avatar',item,'connect'); } }, hall_ip:{ name:'联机大厅', input:true, frequent:true, }, hall_button:{ name:'联机大厅按钮', init:true, frequent:true, onclick:function(bool){ game.saveConfig('hall_button',bool,'connect'); if(ui.hall_button){ if(bool){ ui.hall_button.style.display=''; } else{ ui.hall_button.style.display='none'; } } } }, wss_mode:{ name:'使用WSS协议', init:false, frequent:true, intro:'在用户填写的IP地址没有直接指定使用WS/WSS协议的情况下,默认使用WSS协议,而非WS协议来连接到联机服务器。
    请不要轻易勾选此项!', }, } }, boss:{ name:'挑战', config:{ free_choose:{ name:'自由选将', init:true, frequent:true, onclick:function(bool){ game.saveConfig('free_choose',bool,this._link.config.mode); if(get.mode()!=this._link.config.mode||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat2&&get.config('free_choose')) ui.create.cheat2(); else if(ui.cheat2&&!get.config('free_choose')){ ui.cheat2.close(); delete ui.cheat2; } } }, change_choice:{ name:'开启换将卡', init:true, onclick:function(bool){ game.saveConfig('change_choice',bool,this._link.config.mode); if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat&&get.config('change_choice')) ui.create.cheat(); else if(ui.cheat&&!get.config('change_choice')){ ui.cheat.close(); delete ui.cheat; } }, frequent:true, }, single_control:{ name:'单人控制', init:true, frequent:true, onclick:function(bool){ game.saveConfig('single_control',bool,this._link.config.mode); if(ui.single_swap&&game.me!=game.boss){ if(bool){ ui.single_swap.style.display='none'; } else{ ui.single_swap.style.display=''; } } }, intro:'只控制一名角色,其他角色由AI控制' }, // ban_weak:{ // name:'屏蔽弱将', // init:true, // restart:true, // }, // ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true, // }, } }, doudizhu:{ name:'斗地主', connect:{ update:function(config,map){ if(config.connect_doudizhu_mode=='online'){ map.connect_change_card.hide(); } else{ map.connect_change_card.show(); } if(config.connect_doudizhu_mode!='normal'){ map.connect_double_character.hide(); } else{ map.connect_double_character.show(); } }, connect_doudizhu_mode:{ name:'游戏模式', init:'normal', item:{ normal:'休闲', kaihei:'开黑', huanle:'欢乐', binglin:'兵临', online:'智斗', }, restart:true, frequent:true, }, connect_double_character:{ name:'双将模式', init:false, frequent:true, restart:true, }, connect_change_card:{ name:'启用手气卡', init:false, frequent:true, restart:true, }, }, config:{ update:function(config,map){ if(config.doudizhu_mode=='online'){ map.change_card.hide(); map.edit_character.show(); map.reset_character.show(); } else{ map.change_card.show(); map.edit_character.hide(); map.reset_character.hide(); } if(config.doudizhu_mode!='normal'){ map.double_character.hide(); map.free_choose.hide(); map.change_identity.hide(); map.change_choice.hide(); map.continue_game.hide(); map.dierestart.hide(); map.choice_zhu.hide(); map.choice_fan.hide(); map.revive.hide(); } else{ map.double_character.show(); map.free_choose.show(); map.change_identity.show(); map.change_choice.show(); map.continue_game.show(); map.dierestart.show(); map.choice_zhu.show(); map.choice_fan.show(); map.revive.show(); } if(config.double_character&&config.doudizhu_mode=='normal'){ map.double_hp.show(); } else{ map.double_hp.hide(); } }, doudizhu_mode:{ name:'游戏模式', init:'normal', item:{ normal:'休闲', kaihei:'开黑', huanle:'欢乐', binglin:'兵临', online:'智斗', }, restart:true, frequent:true, }, double_character:{ name:'双将模式', init:false, frequent:true, restart:true, }, double_hp:{ name:'双将体力上限', init:'pingjun', item:{ hejiansan:'和减三', pingjun:'平均值', zuidazhi:'最大值', zuixiaozhi:'最小值', zonghe:'相加', }, restart:true, }, free_choose:{ name:'自由选将', init:true, onclick:function(bool){ game.saveConfig('free_choose',bool,this._link.config.mode); if(get.mode()!=this._link.config.mode||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat2&&get.config('free_choose')) ui.create.cheat2(); else if(ui.cheat2&&!get.config('free_choose')){ ui.cheat2.close(); delete ui.cheat2; } } }, change_identity:{ name:'自由选择身份和座位', init:true, onclick:function(bool){ game.saveConfig('change_identity',bool,this._link.config.mode); if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; var dialog; if(ui.cheat2&&ui.cheat2.backup) dialog=ui.cheat2.backup; else dialog=_status.event.dialog; if(!_status.brawl||!_status.brawl.noAddSetting){ if(!dialog.querySelector('table')&&get.config('change_identity')) _status.event.getParent().addSetting(dialog); else _status.event.getParent().removeSetting(dialog); } ui.update(); } }, change_choice:{ name:'开启换将卡', init:true, onclick:function(bool){ game.saveConfig('change_choice',bool,this._link.config.mode); if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat&&get.config('change_choice')) ui.create.cheat(); else if(ui.cheat&&!get.config('change_choice')){ ui.cheat.close(); delete ui.cheat; } } }, change_card:{ name:'开启手气卡', init:'disabled', item:{ disabled:'禁用', once:'一次', twice:'两次', unlimited:'无限', }, }, continue_game:{ name:'显示再战', init:false, onclick:function(bool){ game.saveConfig('continue_game',bool,this._link.config.mode); if(get.config('continue_game')){ if(!ui.continue_game&&_status.over&&!_status.brawl&&!game.no_continue_game){ ui.continue_game=ui.create.control('再战',game.reloadCurrent); } } else if(ui.continue_game){ ui.continue_game.close(); delete ui.continue_game; } }, intro:'游戏结束后可选择用相同的武将再进行一局游戏' }, dierestart:{ name:'死亡后显示重来', init:true, onclick:function(bool){ game.saveConfig('dierestart',bool,this._link.config.mode); if(get.config('dierestart')){ if(!ui.restart&&game.me.isDead()&&!_status.connectMode){ ui.restart=ui.create.control('restart',game.reload); } } else if(ui.restart){ ui.restart.close(); delete ui.restart; } } }, revive:{ name:'死亡后显示复活', init:false, onclick:function(bool){ game.saveConfig('revive',bool,this._link.config.mode); if(get.config('revive')){ if(!ui.revive&&game.me.isDead()){ ui.revive=ui.create.control('revive',ui.click.dierevive); } } else if(ui.revive){ ui.revive.close(); delete ui.revive; } } }, choice_zhu:{ name:'地主候选武将数', init:'3', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, choice_fan:{ name:'农民候选武将数', init:'3', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, edit_character:{ name:'编辑将池', clear:true, onclick:function(){ if(get.mode()!='doudizhu'){ alert('请进入斗地主模式,然后再编辑将池'); return; } var container=ui.create.div('.popup-container.editor'); var node=container; var map=get.config('character_online')||lib.characterOnline; node.code='character='+get.stringify(map)+'\n/*\n 这里是智斗三国模式的武将将池。\n 您可以在这里编辑对武将将池进行编辑,然后点击“保存”按钮即可保存。\n 将池中的Key势力武将,仅同时在没有被禁用的情况下,才会出现在选将框中。\n 而非Key势力的武将,只要所在的武将包没有被隐藏,即可出现在选将框中。\n 该将池为单机模式/联机模式通用将池。在这里编辑后,即使进入联机模式,也依然会生效。\n 但联机模式本身禁用的武将(如神貂蝉)不会出现在联机模式的选将框中。\n*/'; ui.window.classList.add('shortcutpaused'); ui.window.classList.add('systempaused'); var saveInput=function(){ var code; if(container.editor){ code=container.editor.getValue(); } else if(container.textarea){ code=container.textarea.value; } try{ var character=null; eval(code); if(!get.is.object(character)){ throw('err'); } var groups=[]; for(var i in character){ if(!Array.isArray(character[i])) throw('type'); if(character[i].length>=3) groups.push(i); } if(groups.length<3) throw('enough'); } catch(e){ if(e=='type'){ alert('请严格按照格式填写,不要写入不为数组的数据'); } else if(e=='enough'){ alert('请保证至少写入了3个势力,且每个势力至少有3个武将'); } else if(e=='err'){ alert('代码格式有错误,请对比示例代码仔细检查'); } else{ var tip=lib.getErrorTip(e)||''; alert('代码语法有错误,请仔细检查('+e+')'+tip); } window.focus(); if(container.editor){ container.editor.focus(); } else if(container.textarea){ container.textarea.focus(); } return; } game.saveConfig('character_online',character,'doudizhu'); ui.window.classList.remove('shortcutpaused'); ui.window.classList.remove('systempaused'); container.delete(); container.code=code; delete window.saveNonameInput; }; window.saveNonameInput=saveInput; var editor=ui.create.editor(container,saveInput); if(node.aced){ ui.window.appendChild(node); node.editor.setValue(node.code,1); } else if(lib.device=='ios'){ ui.window.appendChild(node); if(!node.textarea){ var textarea=document.createElement('textarea'); editor.appendChild(textarea); node.textarea=textarea; lib.setScroll(textarea); } node.textarea.value=node.code; } else{ if(!window.CodeMirror){ lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,editor)); lib.init.css(lib.assetURL+'layout/default','codemirror'); } else{ lib.codeMirrorReady(node,editor); } }; }, }, reset_character:{ name:'重置将池', intro:'将智斗三国模式下的将池重置为默认将池', clear:true, onclick:function(){ if(confirm('该操作不可撤销!是否清除智斗三国模式的自定义将池,并将其重置为默认将池?')){ game.saveConfig('character_online',null,'doudizhu'); alert('将池已重置'); } }, }, } }, single:{ name:'单挑', connect:{ connect_single_mode:{ name:'游戏模式', init:'normal', item:{ normal:'新1v1', dianjiang:'点将单挑', changban:'血战长坂坡', }, restart:true, frequent:true, }, connect_enable_jin:{ name:'启用晋势力武将', init:false, restart:true, frequent:true, }, update:function(config,map){ if(config.connect_single_mode!='normal'){ map.connect_enable_jin.hide(); } else{ map.connect_enable_jin.show(); } }, }, config:{ single_mode:{ name:'游戏模式', init:'normal', item:{ normal:'新1v1', dianjiang:'点将单挑', changban:'血战长坂坡', }, restart:true, frequent:true, }, enable_jin:{ name:'启用晋势力武将', init:false, restart:true, frequent:true, }, update:function(config,map){ if(config.single_mode!='normal'){ map.enable_jin.hide(); } else{ map.enable_jin.show(); } }, } }, chess:{ name:'战棋', config:{ chess_mode:{ name:'游戏模式', init:'combat', item:{ combat:'自由', three:'统率', leader:'君主', }, restart:true, frequent:true, }, update:function(config,map){ if(config.chess_mode=='leader'){ map.chess_leader_save.show(); map.chess_leader_clear.show(); map.chess_leader_allcharacter.show(); map.chess_character.hide(); } else{ map.chess_leader_save.hide(); map.chess_leader_clear.hide(); map.chess_leader_allcharacter.hide(); map.chess_character.show(); } if(config.chess_mode=='combat'){ // map.battle_number.show(); // map.chess_ordered.show(); map.free_choose.show(); map.change_choice.show(); } else{ // map.battle_number.hide(); // map.chess_ordered.hide(); map.free_choose.hide(); map.change_choice.hide(); } // if(config.chess_mode!='leader'){ // map.ban_weak.show(); // map.ban_strong.show(); // } // else{ // map.ban_weak.hide(); // map.ban_strong.hide(); // } }, chess_leader_save:{ name:'选择历程', init:'save1', item:{ save1:'一', save2:'二', save3:'三', save4:'四', save5:'五', }, restart:true, frequent:true, }, chess_leader_allcharacter:{ name:'启用全部角色', init:true, onclick:function(bool){ if(confirm('调整该设置将清除所有进度,是否继续?')){ for(var i=1;i<6;i++) game.save('save'+i,null,'chess'); game.saveConfig('chess_leader_allcharacter',bool,'chess') if(get.mode()=='chess') game.reload(); return; } else this.classList.toggle('on'); }, }, chess_leader_clear:{ name:'清除进度', onclick:function(){ var node=this; if(node._clearing){ for(var i=1;i<6;i++) game.save('save'+i,null,'chess'); game.reload(); return; } node._clearing=true; node.firstChild.innerHTML='单击以确认 (3)'; setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (2)'; setTimeout(function(){ node.firstChild.innerHTML='单击以确认 (1)'; setTimeout(function(){ node.firstChild.innerHTML='清除进度'; delete node._clearing; },1000); },1000); },1000); }, clear:true, frequent:true, }, // chess_treasure:{ // name:'战场机关', // init:'0', // frequent:true, // item:{ // '0':'关闭', // '0.1':'较少出现', // '0.2':'偶尔出现', // '0.333':'时常出现', // '0.5':'频繁出现', // } // }, chess_obstacle:{ name:'随机路障', init:'0.2', item:{ '0':'关闭', '0.2':'少量', '0.333':'中量', '0.5':'大量', }, frequent:true, }, show_range:{ name:'显示卡牌范围', init:true, }, show_distance:{ name:'显示距离', init:true, }, chess_character:{ name:'战棋武将', init:true, frequent:true, }, chess_card:{ name:'战棋卡牌', init:true, frequent:true, }, free_choose:{ name:'自由选将', init:true, onclick:function(bool){ game.saveConfig('free_choose',bool,this._link.config.mode); if(get.mode()!=this._link.config.mode||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat2&&get.config('free_choose')) ui.create.cheat2(); else if(ui.cheat2&&!get.config('free_choose')){ ui.cheat2.close(); delete ui.cheat2; } }, }, change_choice:{ name:'开启换将卡', init:true, onclick:function(bool){ game.saveConfig('change_choice',bool,this._link.config.mode); if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat&&get.config('change_choice')) ui.create.cheat(); else if(ui.cheat&&!get.config('change_choice')){ ui.cheat.close(); delete ui.cheat; } }, }, // ban_weak:{ // name:'屏蔽弱将', // init:true, // restart:true, // }, // ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true, // }, chessscroll_speed:{ name:'边缘滚动速度', init:'20', intro:'鼠标移至屏幕边缘时自动滚屏', item:{ '0':'不滚动', '10':'10格/秒', '20':'20格/秒', '30':'30格/秒', } }, } }, tafang:{ name:'塔防', config:{ tafang_turn:{ name:'游戏胜利', init:'10', frequent:true, item:{ '10':'十回合', '20':'二十回合', '30':'三十回合', '1000':'无限', } }, // tafang_size:{ // name:'战场大小', // init:'9', // frequent:true, // item:{ // '6':'小', // '9':'中', // '12':'大', // } // }, tafang_difficulty:{ name:'战斗难度', init:'2', frequent:true, item:{ '1':'简单', '2':'普通', '3':'困难', } }, show_range:{ name:'显示卡牌范围', init:true, }, show_distance:{ name:'显示距离', init:true, }, // ban_weak:{ // name:'屏蔽弱将', // init:true, // restart:true, // }, // ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true, // }, chessscroll_speed:{ name:'边缘滚动速度', intro:'鼠标移至屏幕边缘时自动滚屏', init:'20', item:{ '0':'不滚动', '10':'10格/秒', '20':'20格/秒', '30':'30格/秒', } }, } }, brawl:{ name:'乱斗', config:{ huanhuazhizhan:{ name:'幻化之战', init:true, frequent:true }, duzhansanguo:{ name:'毒战三国', init:true, frequent:true }, daozhiyueying:{ name:'导师月英', init:true, frequent:true }, weiwoduzun:{ name:'唯我独尊', init:true, frequent:true }, tongxingzhizheng:{ name:'同姓之争', init:true, frequent:true }, jiazuzhizheng:{ name:'家族之争', init:true, frequent:true }, tongqueduopao:{ name:'铜雀夺袍', init:true, frequent:true }, tongjiangmoshi:{ name:'同将模式', init:true, frequent:true }, baiyidujiang:{ name:'白衣渡江', init:true, frequent:true }, qianlidanji:{ name:'千里单骑', init:true, frequent:true }, liangjunduilei:{ name:'两军对垒', init:true, frequent:true }, scene:{ name:'创建场景', init:true, frequent:true } } }, stone:{ name:'炉石', config:{ // update:function(config,map){ // if(config.stone_mode=='deck'){ // // map.deck_length.show(); // // map.deck_repeat.show(); // map.random_length.hide(); // map.skill_bar.show(); // } // else{ // // map.deck_length.hide(); // // map.deck_repeat.hide(); // map.random_length.show(); // map.skill_bar.hide(); // } // }, // stone_mode:{ // name:'游戏模式', // init:'deck', // item:{ // deck:'构筑', // random:'随机' // }, // restart:true, // frequent:true, // }, // deck_length:{ // name:'卡组长度', // init:'30', // item:{ // '30':'30张', // '50':'50张', // '80':'80张', // }, // frequent:true, // }, // deck_repeat:{ // name:'重复卡牌', // init:'2', // item:{ // '2':'2张', // '3':'3张', // '5':'5张', // '80':'无限', // }, // frequent:true, // }, // random_length:{ // name:'随从牌数量', // init:'1/80', // item:{ // '1/120':'少', // '1/80':'中', // '1/50':'多', // }, // frequent:true, // }, battle_number:{ name:'出场人数', init:'1', frequent:true, item:{ '1':'一人', '2':'两人', '3':'三人', '4':'四人', '6':'六人', '8':'八人', '10':'十人', }, onclick:function(num){ game.saveConfig('battle_number',num,this._link.config.mode); if(_status.connectMode) return; if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(_status.event.getParent().changeDialog){ _status.event.getParent().changeDialog(); } }, }, mana_mode:{ name:'行动值变化', init:'inc', item:{ inf:'涨落', inc:'递增' }, frequent:true }, skill_bar:{ name:'怒气值', init:true, frequent:true, restart:true, }, double_character:{ name:'双将模式', init:false, frequent:true, restart:function(){ return _status.event.getParent().name!='chooseCharacter'||_status.event.name!='chooseButton'; } }, free_choose:{ name:'自由选将', init:true, onclick:function(bool){ game.saveConfig('free_choose',bool,this._link.config.mode); if(_status.connectMode) return; if(get.mode()!=this._link.config.mode||!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat2&&get.config('free_choose')) ui.create.cheat2(); else if(ui.cheat2&&!get.config('free_choose')){ ui.cheat2.close(); delete ui.cheat2; } }, }, change_choice:{ name:'开启换将卡', init:true, onclick:function(bool){ game.saveConfig('change_choice',bool,this._link.config.mode); if(_status.connectMode) return; if(!_status.event.getParent().showConfig&&!_status.event.showConfig) return; if(!ui.cheat&&get.config('change_choice')) ui.create.cheat(); else if(ui.cheat&&!get.config('change_choice')){ ui.cheat.close(); delete ui.cheat; } }, }, // ban_weak:{ // name:'屏蔽弱将', // init:true, // restart:true, // }, // ban_strong:{ // name:'屏蔽强将', // init:false, // restart:true, // }, } }, }, status:{ running:false, canvas:false, time:0, reload:0, delayed:0, frameId:0, videoId:0, globalId:0, }, help:{ '关于游戏':'
    关于无名杀
    • 无名杀官方发布地址仅有GitHub仓库!
      点击前往Github仓库
    • 无名杀基于GPLv3开源协议。
      点击查看GPLv3协议
    • 其他所有的所谓“无名杀”社群(包括但不限于绝大多数“官方”QQ群、QQ频道等)均为玩家自发组织,与无名杀官方无关!', '游戏操作':'
      • 长按/鼠标悬停/右键单击显示信息。
      • 触屏模式中,双指点击切换暂停;下划显示菜单,上划切换托管。
      • 键盘快捷键
        '+ '
        A切换托管
        W切换不询问无懈
        空格暂停
      • 编辑牌堆
        在卡牌包中修改牌堆后,将自动创建一个临时牌堆,在所有模式中共用,当保存当前牌堆后,临时牌堆被清除。每个模式可设置不同的已保存牌堆,设置的牌堆优先级大于临时牌堆。
      ', '游戏命令':'
      变量名
      • 场上角色
        game.players
      • 阵亡角色
        game.dead'+ '
      • 玩家
        game.me
      • 玩家的上/下家
        game.me.previous/next'+ '
      • 玩家的上/下家(含阵亡)
        game.me.previousSeat/
        nextSeat'+ '
      • 牌堆
        ui.cardPile
      • 弃牌堆
        ui.discardPile
      '+ '
      角色属性
      • 体力值
        player.hp'+ '
      • 体力上限
        player.maxHp
      • 身份
        player.identity
      • 手牌
        player.getCards("h")
      • 装备牌
        player.getCards("e")
      • 判定牌
        player.getCards("j")'+ '
      • 是否存活/横置/翻面
        player.isAlive()/
        isLinked()/
        isTurnedOver()
      '+ '
      角色操作
      • 受到伤害
        player.damage(source,
        num)'+ '
      • 回复体力
        player.recover(num)
      • 摸牌
        player.draw(num)
      • 获得牌
        player.gain(cards)
      • 弃牌
        player.discard(cards)'+ '
      • 使用卡牌
        player.useCard(card,
        targets)
      • 死亡
        player.die()
      • 复活
        player.revive(hp)
      '+ '
      游戏操作
      • 在命令框中输出结果
        game.print(str)
      • 清除命令框中的内容
        cls
      • 上一条/下一条输入的内容
        up/down
      • 游戏结束
        game.over(bool)'+ '
      • 角色资料
        lib.character
      • 卡牌资料
        lib.card
      ', '游戏名词':'
      • 智囊:无名杀默认为过河拆桥/无懈可击/无中生有/洞烛先机。牌堆中没有的智囊牌会被过滤。可在卡牌设置中自行增减。若没有可用的智囊,则改为随机选取的三种锦囊牌的牌名。'+ '
      • 仁库:部分武将使用的游戏外共通区域。至多包含六张牌。当有新牌注入后,若牌数超过上限,则将最早进入仁库的溢出牌置入弃牌堆。'+ '
      • 护甲:和体力类似,每点护甲可抵挡1点伤害,但不影响手牌上限。'+ '
      • 随从:通过技能获得,拥有独立的技能、手牌区和装备区(共享判定区),出场时替代主武将的位置;随从死亡时自动切换回主武将。'+ '
      • 发现:从三张随机亮出的牌中选择一张,若无特殊说明,则获得此牌。'+ '
      • 蓄能技:发动时可以增大黄色的数字。若如此做,红色数字于技能的结算过程中改为原来的两倍。'+ '
      • 施法:若技能的拥有者未拥有等待执行的同名“施法”效果,则其可以发动“施法”技能。其须选择声明一个数字X(X∈[1, 3]),在此之后的第X个回合结束时,其执行“施法”效果,且效果中的数字X视为与技能发动者声明的X相同。'+ '
      • 共同拼点:一种特殊的拼点结算。发起者与被指定的拼点目标同时亮出拼点牌,进行一次决算:其中拼点牌点数唯一最大的角色赢,其他角色均没赢;若没有点数唯一最大的拼点牌,则所有角色拼点均没赢。'+ '
      • 强令:若一名角色拥有带有“强令”的技能,则该技能的发动时机为“出牌阶段开始时”。若技能拥有者发动该技能,其须发布“强令”给一名其他角色,并在对应技能的时间节点加以判断目标角色是否成功完成该强令所要求的任务条件。成功或失败则会根据技能效果执行不同结算流程。'+ '
      • 摧坚:若一名角色拥有带有“摧坚”的技能,则该技能的发动时机为“当你使用伤害牌指定第一个目标后”。你可以对其中一个目标发动“摧坚”技能,然后执行后续效果。其中,后续效果里的X等于该目标的非charlotte技能的数量。'+ '
      • 妄行:一种特殊的选项。若一名角色拥有带有“妄行”的技能,则该技能触发时,你须选择声明一个数字X(X∈{1,2,3,4}),技能后续中的X即为你选择的数字。选择完毕后,你获得如下效果:回合结束时,你选择一项:1.弃置X张牌;2.减1点体力上限。'+ '
      • 搏击:若一名角色拥有带有“搏击”的技能,则当该搏击技能触发时,若本次技能的目标角色在你攻击范围内,且你在其攻击范围内,则你执行技能主体效果时,同时额外执行“搏击”后的额外效果。'+ '
      • 游击:若一名角色拥有带有“游击”的技能,则当该游击技能执行至“游击”处时,若本次技能的目标角色在你的攻击范围内,且你不在其攻击范围内,则你可以执行“游击”后的额外效果。'+ '
      • 激昂:一名角色发动“昂扬技”标签技能后,此技能失效,直至从此刻至满足此技能“激昂”条件后。'+ '' }, /** * @type {import('path')} */ path:{}, getErrorTip:msg=>{ if(typeof msg!='string'){ try{ msg=msg.toString(); if(typeof msg!='string') throw 'err'; }catch(_){ throw '传参错误:'+msg; } } if (msg.startsWith('Uncaught ')) msg=msg.slice(9); let newMessage=msg; if (/RangeError/.test(newMessage)){ if(newMessage.includes("Maximum call stack size exceeded")){ newMessage="堆栈溢出"; }else if(/argument must be between 0 and 20/.test(newMessage)){ let funName=newMessage.slice(newMessage.indexOf('RangeError: ')+12,newMessage.indexOf(')')+1); newMessage=funName+"参数必须在0和20之间"; } else { newMessage="传递错误值到数值计算方法"; } }else if(/ReferenceError/.test(newMessage)){ let messageName; if (newMessage.includes("is not defined")){ messageName=newMessage.replace('ReferenceError: ', '').replace(' is not defined', ''); newMessage="引用了一个未定义的变量:"+messageName; }else if(newMessage.includes("invalid assignment left-hand side")){ newMessage = "赋值运算符或比较运算符不匹配"; }else if(newMessage.includes("Octal literals are not allowed in strict mode")){ newMessage = "八进制字面量与八进制转义序列语法已经被废弃"; }else if(newMessage.includes("Illegal 'use strict' directive in function with non-simple parameter list")){ newMessage = "'use strict'指令不能使用在带有‘非简单参数’列表的函数"; }else if(newMessage.includes("Invalid left-hand side in assignment")){ newMessage = "赋值中的左侧无效,即number,string等不可赋值的非变量数据"; } }else if(/SyntaxError/.test(newMessage)){ let messageName; if(newMessage.includes("Unexpected token ")){ messageName=newMessage.replace('SyntaxError: Unexpected token ',''); newMessage="使用了未定义或错误的语法 : ("+messageName+")"; }else if(newMessage.includes( "Block-scoped declarations (let, const, function, class) not yet supported outside strict mode")){ newMessage="请在严格模式下运行let,const,class"; }else if(newMessage.includes("for-of loop variable declaration may not have an initializer.")){ newMessage="for...of 循环的头部包含有初始化表达式"; }else if(newMessage.includes("for-in loop variable declaration may not have an initializer.")){ newMessage="for...in 循环的头部包含有初始化表达式"; }else if(newMessage.includes("Delete of an unqualified identifier in strict mode.")){ newMessage="普通变量不能通过 delete 操作符来删除"; }else if(newMessage.includes("Unexpected identifier")){ newMessage="不合法的标识符或错误的语法"; }else if(newMessage.includes("Invalid or unexpected token")){ newMessage="非法的或者不期望出现的标记符号出现在不该出现的位置"; }else if(newMessage.includes("Invalid regular expression flags")){ newMessage="无效的正则表达式的标记"; }else if(newMessage.includes("missing ) after argument list")){ newMessage="参数列表后面缺少 \')\' (丢失运算符或者转义字符等)"; }else if(newMessage.includes("Invalid shorthand property initializer")){ newMessage="在定义一个{}对象时,应该使用\':\'而不是\'=\'"; }else if(newMessage.includes("Missing initializer in const declaration")){ newMessage="在使用const定义一个对象时,必须指定初始值"; }else if(newMessage.includes("Unexpected number")||newMessage.includes("Unexpected string")){ newMessage="在定义函数时,函数参数必须为合法标记符"; }else if(newMessage.includes("Unexpected end of input")){ newMessage="遗漏了符号或符号顺序不对(小括号,花括号等)"; }else if(newMessage.includes("has already been declared")){ messageName=newMessage.replace('SyntaxError: Identifier ', '').replace(' has already been declared', ''); newMessage=messageName +"变量已经被声明过,不能被重新声明"; }else if(newMessage.includes("Duplicate parameter name not allowed in this context")) { newMessage="参数名不允许重复"; }else if(newMessage.includes("Unexpected reserved word")||newMessage.includes( "Unexpected strict mode reserved word")){ newMessage = "保留字被用作标记符"; } }else if(/TypeError/.test(newMessage)){ let messageName; if(newMessage.includes(" is not a function")){ messageName=newMessage.replace('TypeError: ', '').replace(' is not a function', ''); newMessage=messageName+"不是一个函数"; }else if(newMessage.includes(" is not a constructor")){ messageName=newMessage.replace('TypeError: ', '').replace(' is not a constructor', ''); newMessage=messageName+"不是一个构造函数"; }else if(newMessage.includes("Cannot read property")){ messageName=newMessage.replace('TypeError: Cannot read property ', '').replace(' of null', '').replace(' of undefined', ''); let ofName=newMessage.slice(newMessage.indexOf(" of ")+4); newMessage="无法读取\'"+ofName+"\'的属性值"+messageName; }else if(newMessage.includes("Cannot read properties")){ messageName=newMessage.slice(newMessage.indexOf("reading '")+9,-2); let ofName=newMessage.slice(newMessage.indexOf(" of ")+4,newMessage.indexOf("(")-1); newMessage="无法读取\'"+ofName+"\'的属性值"+messageName; }else if(newMessage.includes("Property description must be an object")){ messageName=newMessage.replace('TypeError: Property description must be an object: ', ''); newMessage=messageName+"是非对象类型的值"; }else if(newMessage.includes("Cannot assign to read only property ")){ messageName=newMessage.slice(47,newMessage.lastIndexOf(' of ')+1); newMessage=messageName+"属性禁止写入"; }else if(newMessage.includes("Object prototype may only be an Object or null")){ newMessage=messageName+"对象原型只能是对象或null"; }else if(newMessage.includes("Cannot create property")){ messageName=newMessage.slice(newMessage.indexOf('\'')+1); messageName=messageName.slice(0,messageName.indexOf('\'')); let obj=newMessage.slice(newMessage.indexOf(messageName)+16); newMessage=obj+"不能添加或修改\'"+messageName+"\'属性,任何 Primitive 值都不允许有property"; }else if(newMessage.includes("Can't add property")&&newMessage.includes("is not extensible")){ newMessage="对象不可添加属性(不可扩展)"; }else if(newMessage.includes("Cannot redefine property")){ messageName=newMessage.slice(37); newMessage=messageName+"不可配置"; }else if(newMessage.includes("Converting circular structure to JSON")){ messageName=newMessage.slice(37); newMessage="JSON.stringify() 方法处理循环引用结构的JSON会失败"; }else if(newMessage.includes("Cannot use 'in' operator to search for ")){ newMessage="in不能用来在字符串、数字或者其他基本类型的数据中进行检索"; }else if(newMessage.includes("Right-hand side of 'instanceof' is not an object")){ newMessage="instanceof 操作符 希望右边的操作数为一个构造对象,即一个有 prototype 属性且可以调用的对象"; }else if(newMessage.includes("Assignment to constant variable")){ newMessage="const定义的变量不可修改"; }else if(newMessage.includes("Cannot delete property")){ newMessage="不可配置的属性不能删除"; }else if(newMessage.includes("which has only a getter")){ newMessage="仅设置了getter特性的属性不可被赋值"; }else if(newMessage.includes("called on incompatible receiver undefined")){ newMessage="this提供的绑定对象与预期的不匹配"; } }else if(/URIError/.test(newMessage)){ newMessage="一个不合法的URI"; }else if(/EvalError/.test(newMessage)){ newMessage="非法调用 eval()"; }else if(/InternalError/.test(newMessage)){ if(newMessage.includes("too many switch cases")){ newMessage="过多case子句"; }else if(newMessage.includes("too many parentheses in regular expression")){ newMessage="正则表达式中括号过多"; }else if(newMessage.includes("array initializer too large")){ newMessage="超出数组大小的限制"; }else if(newMessage.includes("too much recursion")){ newMessage="递归过深"; } } if(newMessage!=msg){ return newMessage; } }, codeMirrorReady:(node,editor)=>{ ui.window.appendChild(node); node.style.fontSize=20/game.documentZoom+'px'; const mirror=window.CodeMirror(editor,{ value:node.code, mode:"javascript", lineWrapping:!lib.config.touchscreen&&lib.config.mousewheel, lineNumbers:true, indentUnit:4, autoCloseBrackets:true, fixedGutter:false, hintOptions:{completeSingle:false}, theme:lib.config.codeMirror_theme||'mdn-like', extraKeys:{ "Ctrl-Z":"undo",//撤销 "Ctrl-Y":"redo",//恢复撤销 //"Ctrl-A":"selectAll",//全选 }, }); lib.setScroll(editor.querySelector('.CodeMirror-scroll')); node.aced=true; node.editor=mirror; setTimeout(()=>mirror.refresh(),0); node.editor.on('change',(e,change)=>{ let code; if(node.editor){ code=node.editor.getValue(); }else if(node.textarea){ code=node.textarea.value; }; //动态绑定文本 if(code.length&&change.origin=="+input" && /{|}|\s|=|;|:|,|,|。|?|!|\!|\?|&|#|%|@|‘|’|;/.test(change.text[0])==false&& change.text.length==1) { //输入了代码,并且不包括空格,{},=, ; , : , 逗号等,才可以自动提示 node.editor.showHint(); } }); //防止每次输出字符都创建以下元素 const event=_status.event; const trigger=_status.event; const player=ui.create.player().init('sunce'); const target=player; const targets=[player]; const source=player; const card=game.createCard(); const cards=[card]; const result={bool:true}; function forEach(arr,f) { Array.from(arr).forEach(v=>f(v)); } function forAllProps(obj,callback){ if(!Object.getOwnPropertyNames||!Object.getPrototypeOf){ for(let name in obj) callback(name); }else{ for(let o=obj;o;o=Object.getPrototypeOf(o)) Object.getOwnPropertyNames(o).forEach(callback); } } function scriptHint(editor,keywords,getToken,options){ //Find the token at the cursor let cur=editor.getCursor(),token=editor.getTokenAt(cur); if(/\b(?:string|comment)\b/.test(token.type)) return; const innerMode=CodeMirror.innerMode(editor.getMode(),token.state); if (innerMode.mode.helperType==="json") return; token.state=innerMode.state; //If it's not a 'word-style' token, ignore the token. if (!/^[\w$_]*$/.test(token.string)){ token={ start:cur.ch, end:cur.ch, string:"", state:token.state, type:token.string=="."?"property":null }; }else if(token.end>cur.ch){ token.end=cur.ch; token.string=token.string.slice(0,cur.ch-token.start); } let tprop=token,context; //If it is a property, find out what it is a property of. while (tprop.type=="property"){ tprop=editor.getTokenAt(CodeMirror.Pos(cur.line,tprop.start)); if(tprop.string!=".") return; tprop=editor.getTokenAt(CodeMirror.Pos(cur.line,tprop.start)); if(!context) context=[]; context.push(tprop); } const list=[]; let obj; if(Array.isArray(context)){ try { const code=context.length==1?context[0].string:context.reduceRight((pre,cur)=>(pre.string||pre)+'.'+cur.string); obj=eval(code); if(![null,undefined].includes(obj)){ const keys=Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(obj))).filter(key=>key.startsWith(token.string)); list.addArray(keys); } }catch(_){ return;} }else if(token&&typeof token.string=='string'){ //非开发者模式下,提示这些单词 list.addArray(['player','card','cards','result','trigger','source','target','targets','lib','game','ui','get','ai','_status']); } return { list:[...new Set(getCompletions(token,context,keywords,options).concat(list))] .filter(key=>key.startsWith(token.string)) .sort((a,b)=>(a+'').localeCompare(b+'')) .map(text=>{ return { render(elt,data,cur) { var icon=document.createElement("span"); var className="cm-completionIcon cm-completionIcon-"; if(obj){ const type=typeof obj[text]; if(type== 'function') { className+='function'; } else if(type== 'string') { className+='text'; } else if(type== 'boolean') { className+='variable'; } else{ className+='namespace'; } }else{ if(javascriptKeywords.includes(text)){ className+='keyword'; } else if(window[text]) { const type=typeof window[text]; if(type=='function'){ className+='function'; } else if(type=='string'){ className+='text'; } else if(text=='window'||type=='boolean'){ className+='variable'; } else{ className+='namespace'; } }else{ className+='namespace'; } } icon.className=className; elt.appendChild(icon); elt.appendChild(document.createTextNode(text)); }, displayText: text, text: text, } }), from:CodeMirror.Pos(cur.line,token.start), to:CodeMirror.Pos(cur.line,token.end) }; } function javascriptHint(editor,options){ return scriptHint(editor,javascriptKeywords,function(e,cur){return e.getTokenAt(cur);},options); }; //覆盖原本的javascript提示 CodeMirror.registerHelper("hint","javascript",javascriptHint); const stringProps=Object.getOwnPropertyNames(String.prototype); const arrayProps=Object.getOwnPropertyNames(Array.prototype); const funcProps=Object.getOwnPropertyNames(Array.prototype); const javascriptKeywords=("break case catch class const continue debugger default delete do else export extends from false finally for function " + "if in import instanceof let new null return super switch this throw true try typeof var void while with yield").split(" "); function getCompletions(token,context,keywords,options){ let found=[],start=token.string,global=options&&options.globalScope||window; function maybeAdd(str){ if(str.lastIndexOf(start,0)==0&&!found.includes(str)) found.push(str); } function gatherCompletions(obj){ if(typeof obj=="string") forEach(stringProps,maybeAdd); else if(obj instanceof Array) forEach(arrayProps,maybeAdd); else if(obj instanceof Function) forEach(funcProps,maybeAdd); forAllProps(obj, maybeAdd); } if(context&&context.length){ //If this is a property, see if it belongs to some object we can //find in the current environment. let obj=context.pop(),base; if (obj.type&&obj.type.indexOf("variable")=== 0){ if(options&&options.additionalContext) base=options.additionalContext[obj.string]; if(!options||options.useGlobalScope!==false) base=base||global[obj.string]; }else if(obj.type=="string"){ base=""; }else if(obj.type == "atom"){ base=1; }else if(obj.type == "function"){ if(global.jQuery!=null&&(obj.string=='$'||obj.string=='jQuery')&&(typeof global.jQuery=='function')) base=global.jQuery(); else if(global._!=null&&(obj.string=='_')&&(typeof global._=='function')) base=global._(); } while(base!=null&&context.length) base=base[context.pop().string]; if (base!=null) gatherCompletions(base); }else{ //If not, just look in the global object, any local scope, and optional additional-context //(reading into JS mode internals to get at the local and global variables) for(let v=token.state.localVars;v;v=v.next) maybeAdd(v.name); for(let c=token.state.context;c;c=c.prev) for(let v=c.vars;v;v=v.next) maybeAdd(v.name) for(let v=token.state.globalVars;v;v=v.next) maybeAdd(v.name); if(options&&options.additionalContext!=null) for(let key in options.additionalContext) maybeAdd(key); if(!options||options.useGlobalScope!==false) gatherCompletions(global); forEach(keywords,maybeAdd); } return found.sort((a,b)=>(a+'').localeCompare(b+'')); } }, setIntro:function(node,func,left){ if(lib.config.touchscreen){ if(left){ node.listen(ui.click.touchintro); } else{ lib.setLongPress(node,ui.click.intro); } } else{ if(left){ node.listen(ui.click.intro); } if(lib.config.hover_all&&!lib.device){ lib.setHover(node,ui.click.hoverplayer); } if(lib.config.right_info){ node.oncontextmenu=ui.click.rightplayer; } } // if(!left){ // lib.setPressure(node,ui.click.rightpressure); // } if(func){ node._customintro=func; } }, // setPressure:function(node,func){ // if(window.Pressure){ // window.Pressure.set(node,{change: func}, {polyfill: false}); // } // }, setPopped:function(node,func,width,height,forceclick,paused2){ node._poppedfunc=func; node._poppedwidth=width; node._poppedheight=height; if(forceclick){ node.forceclick=true; } if(lib.config.touchscreen||forceclick){ node.listen(ui.click.hoverpopped); } else{ node.addEventListener('mouseenter',ui.click.hoverpopped); // node.addEventListener('mouseleave',ui.click.hoverpopped_leave); } if(paused2){ node._paused2=true; } }, placePoppedDialog:function(dialog,e){ if(dialog._place_text){ if(dialog._place_text.firstChild.offsetWidth>=190||dialog._place_text.firstChild.offsetHeight>=30){ dialog._place_text.style.marginLeft='14px'; dialog._place_text.style.marginRight='14px'; dialog._place_text.style.textAlign='left'; dialog._place_text.style.width='calc(100% - 28px)'; } } if(e.touches&&e.touches[0]){ e=e.touches[0]; } var height=Math.min(ui.window.offsetHeight-20,dialog.content.scrollHeight); if(dialog._mod_height){ height+=dialog._mod_height; } dialog.style.height=height+'px'; if(e.clientX/game.documentZoomui.window.offsetHeight){ idealtop=ui.window.offsetHeight-10-dialog.offsetHeight; } dialog.style.top=idealtop+'px'; }, setHover:function(node,func,hoveration,width){ node._hoverfunc=func; if(typeof hoveration=='number'){ node._hoveration=hoveration; } if(typeof width=='number'){ node._hoverwidth=width } node.addEventListener('mouseenter',ui.click.mouseenter); node.addEventListener('mouseleave',ui.click.mouseleave); node.addEventListener('mousedown',ui.click.mousedown); node.addEventListener('mousemove',ui.click.mousemove); return node; }, setScroll:function(node){ node.ontouchstart=ui.click.touchStart; node.ontouchmove=ui.click.touchScroll; node.style.webkitOverflowScrolling='touch'; return node; }, setMousewheel:function(node){ if(lib.config.mousewheel) node.onmousewheel=ui.click.mousewheel; }, setLongPress:function(node,func){ node.addEventListener('touchstart',ui.click.longpressdown); node.addEventListener('touchend',ui.click.longpresscancel); node._longpresscallback=func; return node; }, updateCanvas:function(time){ if(lib.canvasUpdates.length===0){ lib.status.canvas=false; return false; } ui.canvas.width=ui.arena.offsetWidth; ui.canvas.height=ui.arena.offsetHeight; var ctx=ui.ctx; ctx.shadowBlur=5; ctx.shadowColor='rgba(0,0,0,0.3)'; ctx.strokeStyle='white'; // ctx.lineCap='round'; ctx.lineWidth=3; ctx.save(); for(var i=0;ignc.of(fn), genAwait:item=>gnc.is.generator(item)?gnc.of(function*(){for(const content of item){yield content;}})():Promise.resolve(item), gnc:{ of:fn=>gnc.of(fn), is:{ coroutine:item=>gnc.is.coroutine(item), generatorFunc:item=>gnc.is.generatorFunc(item), generator:item=>gnc.is.generator(item) } }, comparator:{ equals:function(){ if(arguments.length==0) return false; if(arguments.length==1) return true; for(let i=1;i`[${name}]`, isAttr:(name,item)=>`[${name}=${item}]`, inAttr:(name,item)=>`[${name}~=${item}]`, conAttr:(name,item)=>`[${name}*=${item}]`, onAttr:(name,item)=>`[${name}|=${item}]`, bgnAttr:(name,item)=>`[${name}^=${item}]`, endAttr:(name,item)=>`[${name}^=${item}]`, merge:function(){return Array.from(arguments).join(" ");}, of:function(){return Array.from(arguments).join("");}, class:function(){return `.${Array.from(arguments).join(".")}`;}, group:function(){return Array.from(arguments).join(",");}, media:type=>`@media ${type}` }, dom:{ attributes:{ style(name,value){ return { _type:"style", name:name, value:value } } }, inject(element,options){ //处理id和class if(options.identity){ for(const item of options.identity){ if (item.startsWith("#")) element.id = item.slice(1); else element.classList.add(item); } } //处理属性 if(options.attributes){ for(const item in options.attributes) element.setAttribute(item,options.attributes[item]); } //处理样式 if(options.style){ for(const item in options.style) element.style[item] = options.style[item]; } //处理内容 if(options.content){ element.innerHTML=options.content; } //处理子元素 if(options.childs){ for(const item of options.childs){ element.appendChild(item); } } return element; }, generate(){ let result=lib.creation.nullObject; const args=Array.from(arguments); for(const item of args) { switch(typeof item) { case "object": switch (item.constructor) { case Object: case null: if("_type" in item){ const type=item["_type"]; if(!(type in result)) result[type]=lib.creation.nullObject; result[type][item.name]=item.value; } else{ if(!("style" in result)) result.style=lib.creation.nullObject; for(const name in item){ result.style[name]=item[name]; } } break; default: if(!("childs" in result)) result.childs=lib.creation.array; result.childs.add(item); break; } break; case "string": if(/^\.|#/.test(item)){ if(!("identity" in result)) result.identity=lib.creation.array; const identities=item.split(".").filter(Boolean); for(const item of identities) result.identity.add(item); } else result.content = item; break; } } return result; }, attribute(name,value){ return { _type:"attributes", name:name, value:value } }, div(){ const dom=lib.linq.dom; return dom.inject(document.createElement("div"),dom.generate(...arguments)); } } }, init:{ init:function(){ if(typeof __dirname==='string'&&__dirname.length){ var dirsplit=__dirname.split('/'); for(var i=0;i{ this.style.backgroundImage=`url('${src}')`; this.style.backgroundSize="cover"; return this; }); }; HTMLDivElement.prototype.setBackgroundImage=function(img){ this.style.backgroundImage=`url("${lib.assetURL}${img}")`; return this; }, HTMLDivElement.prototype.listen=function(func){ if(lib.config.touchscreen){ this.addEventListener('touchend',function(e){ if(!_status.dragged){ func.call(this,e); } }); var fallback=function(e){ if(!_status.touchconfirmed){ func.call(this,e); } else{ this.removeEventListener('click',fallback); } } this.addEventListener('click',fallback); } else{ this.addEventListener('click',func); } return this; }; HTMLDivElement.prototype.listenTransition=function(func,time){ let done=false; const callback=()=>{ if(!done){ done=true; func.call(this); } clearTimeout(timer); this.removeEventListener('webkitTransitionEnd',callback); }; const timer=setTimeout(callback,time||1000); this.addEventListener('webkitTransitionEnd',callback); return timer; }; HTMLDivElement.prototype.setPosition=function(){ var position; if(arguments.length==4){ position=[]; for(var i=0;i0) top+='+ '+position[1]+'px)'; else top+='- '+Math.abs(position[1])+'px)'; var left='calc('+position[2]+'% '; if(position[3]>0) left+='+ '+position[3]+'px)'; else left+='- '+Math.abs(position[3])+'px)'; this.style.top=top; this.style.left=left; return this; }; HTMLDivElement.prototype.css=function(style){ for(var i in style){ if(i=='innerHTML'){ this.innerHTML=style[i]; } else{ this.style[i]=style[i]; } } return this; }; HTMLTableElement.prototype.get=function(row,col){ if(rowpos.includes(get.position(card,true))); } }); Object.defineProperty(Array.prototype,"someInD",{ configurable:true, enumerable:false, writable:true, value:function(pos){ if(typeof pos!='string') pos='o'; return this.some(card=>pos.includes(get.position(card,true))); } }); Object.defineProperty(Array.prototype,"everyInD",{ configurable:true, enumerable:false, writable:true, value:function(pos){ if(typeof pos!='string') pos='o'; return this.every(card=>pos.includes(get.position(card,true))); } }); /** *@legacy Use {@link Array#includes} instead. */ Object.defineProperty(Array.prototype,"contains",{ configurable:true, enumerable:false, writable:true, value:Array.prototype.includes }); Object.defineProperty(Array.prototype,"containsSome",{ configurable:true, enumerable:false, writable:true, value:function(){ return Array.from(arguments).some(i=>this.includes(i)); } }); Object.defineProperty(Array.prototype,"containsAll",{ configurable:true, enumerable:false, writable:true, value:function(){ return Array.from(arguments).every(i=>this.includes(i)); } }); Object.defineProperty(Array.prototype,"add",{ configurable:true, enumerable:false, writable:true, value:function(){ for(const arg of arguments){ if(this.contains(arg)) continue; this.push(arg); } return this; } }); Object.defineProperty(Array.prototype,"addArray",{ configurable:true, enumerable:false, writable:true, value:function(){ for(const arr of arguments){ for(const item of arr) this.add(item); } return this; } }); Object.defineProperty(Array.prototype,"remove",{ configurable:true, enumerable:false, writable:true, value:function(){ for(const item of arguments){ const pos=this.indexOf(item); if(pos==-1) continue; this.splice(pos,1); } return this; } }); Object.defineProperty(Array.prototype,"removeArray",{ configurable:true, enumerable:false, writable:true, value:function(){ for(const i of Array.from(arguments)) this.remove(...i); return this; } }); Object.defineProperty(Array.prototype,"unique",{ configurable:true, enumerable:false, writable:true, value:function(){ let uniqueArray=[...new Set(this)]; this.length=uniqueArray.length; for(let i=0;ithis.length) num=this.length; let arr=this.slice(0); let list=[]; for(let i=0;itrue)); if(sortBy&&typeof sortBy=='function') list.sort((a,b)=>sortBy(a)-sortBy(b)); else list.sort(); return list[list.length-1]; } }); Object.defineProperty(Array.prototype,"minBy",{ configurable:true, enumerable:false, writable:true, value:function(sortBy,filter){ let list=this.filter(filter||(()=>true)); if(sortBy&&typeof sortBy=='function') list.sort((a,b)=>sortBy(a)-sortBy(b)); else list.sort(); return list[0]; } }); /** * @deprecated * !!!WARNING!!! * Will be deprecated in next verision! * Use {@link VCard#hasNature} instead. */ Object.defineProperty(Object.prototype,'hasNature',{ configurable:true, enumerable:false, writable:true, value:function(nature,player){ var natures=get.natureList(this,player); if(!nature) return natures.length>0; if(nature=='linked') return natures.some(n=>lib.linked.includes(n)); return get.is.sameNature(natures,nature); } }); window.onkeydown=function(e){ if(!ui.menuContainer||!ui.menuContainer.classList.contains('hidden')){ if(e.keyCode==116||((e.ctrlKey||e.metaKey)&&e.keyCode==82)){ if(e.shiftKey){ if(confirm('是否重置游戏?')){ var noname_inited=localStorage.getItem('noname_inited'); var onlineKey=localStorage.getItem(lib.configprefix+'key'); localStorage.clear(); if(noname_inited){ localStorage.setItem('noname_inited',noname_inited); } if(onlineKey){ localStorage.setItem(lib.configprefix+'key',onlineKey); } if(indexedDB) indexedDB.deleteDatabase(lib.configprefix+'data'); game.reload(); return; } } else{ game.reload(); } } else if(e.keyCode==83&&(e.ctrlKey||e.metaKey)){ if(window.saveNonameInput){ window.saveNonameInput(); } e.preventDefault(); e.stopPropagation(); return false; } else if(e.keyCode==74&&(e.ctrlKey||e.metaKey)&&lib.node){ lib.node.debug(); } } else{ game.closePopped(); var dialogs=document.querySelectorAll('#window>.dialog.popped:not(.static)'); for(var i=0;i=10){ if(line>4){ for(let i=line-5;i`${i+1}| ${line==i+1?'⚠️':''}${_line}\n`).toString(); } return showCode; } //协议名须和html一致(网页端防跨域),且文件是js if (typeof src=='string'&&src.startsWith(location.protocol)&&src.endsWith('.js')){ //获取代码 const codes=lib.init.reqSync('local:'+decodeURI(src).replace(lib.assetURL,'').replace(winPath,'')); const lines=codes.split("\n"); str+='\n'+createShowCode(lines); str+='\n-------------'; } //解析parsex里的content fun内容(通常是技能content) else if(err&&err.stack&&err.stack.split('\n')[1].trim().startsWith('at Object.eval [as content]')){ const codes=_status.event.content; if(typeof codes=='function'){ const lines=codes.toString().split("\n"); str+='\n'+createShowCode(lines); str+='\n-------------'; } } } if(err&&err.stack) str+='\n'+decodeURI(err.stack).replace(new RegExp(lib.assetURL,'g'),'').replace(new RegExp(winPath,'g'),''); alert(str); window.ea=Array.from(arguments); window.em=msg; window.el=line; window.ec=column; window.eo=err; game.print(str); if(!lib.config.errstop){ _status.withError=true; game.loop(); } }; if(window.noname_update){ lib.version=window.noname_update.version; lib.changeLog=window.noname_update.changeLog; if(window.noname_update.players){ lib.changeLog.push('players://'+JSON.stringify(window.noname_update.players)); } if(window.noname_update.cards){ lib.changeLog.push('cards://'+JSON.stringify(window.noname_update.cards)); } delete window.noname_update; } var noname_inited=localStorage.getItem('noname_inited'); if(noname_inited&&noname_inited!=='nodejs'){ var ua=userAgent; if(ua.includes('android')){ lib.device='android'; } else if(ua.includes('iphone')||ua.includes('ipad')||ua.includes('macintosh')){ lib.device='ios'; } } if(lib.assetURL.includes('com.widget.noname.qingyao')||lib.assetURL.includes('online.nonamekill.android')){ alert('您正在一个不受信任的闭源客户端上运行《无名杀》。建议您更换为其他开源的无名杀客户端,避免给您带来不必要的损失。'); } var config3=null; var proceed=function(config2){ if(config3===null){ config3=config2; return; } if(config2.mode) lib.config.mode=config2.mode; if(lib.config.mode_config[lib.config.mode]==undefined) lib.config.mode_config[lib.config.mode]={}; for(var i in lib.config.mode_config.global){ if(lib.config.mode_config[lib.config.mode][i]==undefined){ lib.config.mode_config[lib.config.mode][i]=lib.config.mode_config.global[i]; } } if(lib.config.characters){ lib.config.defaultcharacters=lib.config.characters.slice(0); } if(lib.config.cards){ lib.config.defaultcards=lib.config.cards.slice(0); } for(var i in config2){ if(i.includes('_mode_config')){ var thismode=i.substr(i.indexOf('_mode_config')+13); if(!lib.config.mode_config[thismode]){ lib.config.mode_config[thismode]={}; } lib.config.mode_config[thismode][i.substr(0,i.indexOf('_mode_config'))]=config2[i]; } else{ lib.config[i]=config2[i]; } } for(var i in lib.config.translate){ lib.translate[i]=lib.config.translate[i]; } lib.config.all.characters=[]; lib.config.all.cards=[]; lib.config.all.plays=[]; lib.config.all.mode=[]; if(lib.config.debug){ lib.init.js(lib.assetURL+'game','asset',function(){ lib.skin=window.noname_skin_list; delete window.noname_skin_list; delete window.noname_asset_list; }); } if(window.isNonameServer){ lib.config.mode='connect'; } var pack=window.noname_package; delete window.noname_package; for(i in pack.character){ if(lib.config.all.sgscharacters.contains(i)||lib.config.hiddenCharacterPack.indexOf(i)==-1){ lib.config.all.characters.push(i); lib.translate[i+'_character_config']=pack.character[i]; } } for(i in pack.card){ if(lib.config.all.sgscards.contains(i)||lib.config.hiddenCardPack.indexOf(i)==-1){ lib.config.all.cards.push(i); lib.translate[i+'_card_config']=pack.card[i]; } } for(i in pack.play){ lib.config.all.plays.push(i); lib.translate[i+'_play_config']=pack.play[i]; } for(i in pack.submode){ for(var j in pack.submode[i]){ lib.translate[i+'|'+j]=pack.submode[i][j]; } } if(!lib.config.gameRecord){ lib.config.gameRecord={}; } for(i in pack.mode){ if(lib.config.hiddenModePack.indexOf(i)==-1){ lib.config.all.mode.push(i); lib.translate[i]=pack.mode[i]; if(!lib.config.gameRecord[i]){ lib.config.gameRecord[i]={data:{}}; } } } if(lib.config.all.mode.length==0){ lib.config.all.mode.push('identity'); lib.translate.identity='身份'; if(!lib.config.gameRecord.identity){ lib.config.gameRecord.identity={data:{}}; } } if(pack.background){ for(i in pack.background){ if(lib.config.hiddenBackgroundPack.contains(i)) continue; lib.configMenu.appearence.config.image_background.item[i]=pack.background[i]; } for(var i=0;i{ const font=pack.font[value]; appearenceConfig.name_font.item[value]=font; appearenceConfig.identity_font.item[value]=font; appearenceConfig.cardtext_font.item[value]=font; appearenceConfig.global_font.item[value]=font; fontSheet.insertRule(`@font-face {font-family: '${value}'; src: local('${font}'), url('${lib.assetURL}font/${value}.woff2');}`,0); if(suitsFont) fontSheet.insertRule(`@font-face {font-family: '${value}'; src: local('${font}'), url('${lib.assetURL}font/suits.woff2');}`,0); }); if(suitsFont) fontSheet.insertRule(`@font-face {font-family: 'Suits'; src: url('${lib.assetURL}font/suits.woff2');}`,0); fontSheet.insertRule(`@font-face {font-family: 'NonameSuits'; src: url('${lib.assetURL}font/suits.woff2');}`,0); fontSheet.insertRule(`@font-face {font-family: 'MotoyaLMaru'; src: url('${lib.assetURL}font/motoyamaru.woff2');}`,0) appearenceConfig.cardtext_font.item.default='默认'; appearenceConfig.global_font.item.default='默认'; } var ua=userAgent; if('ontouchstart' in document){ if(!lib.config.totouched){ game.saveConfig('totouched',true); if(lib.device){ game.saveConfig('low_performance',true); game.saveConfig('confirm_exit',true); game.saveConfig('touchscreen',true); game.saveConfig('fold_mode',false); if(ua.indexOf('ipad')==-1){ game.saveConfig('phonelayout',true); } else if(lib.device=='ios'){ game.saveConfig('show_statusbar_ios','overlay'); } } else if(confirm('是否切换到触屏模式?(触屏模式可提高触屏设备的响应速度,但无法使用鼠标)')){ game.saveConfig('touchscreen',true); if(ua.includes('iphone')||ua.includes('android')){ game.saveConfig('phonelayout',true); } game.reload(); } } } else if(lib.config.touchscreen){ game.saveConfig('touchscreen',false); } if(!lib.config.toscrolled&&ua.includes('macintosh')){ game.saveConfig('toscrolled',true); game.saveConfig('mousewheel',false); } var show_splash=lib.config.show_splash; if(show_splash=='off'){ show_splash=false; } else if(show_splash=='init'){ if(localStorage.getItem('show_splash_off')){ show_splash=false; } } localStorage.removeItem('show_splash_off'); var extensionlist=[]; if(!localStorage.getItem(lib.configprefix+'disable_extension')){ if(lib.config.extensions&&lib.config.extensions.length){ window.resetExtension=function(){ for(var i=0;i{ const isArray=Array.isArray; if (isArray(lib.onprepare)&&lib.onprepare.length){ _status.onprepare=Object.freeze(lib.onprepare.map(fn=>{ if(typeof fn!="function") return; return (gnc.is.generatorFunc(fn)?gnc.of(fn):fn)(); })); } let toLoad=lib.config.all.cards.length+lib.config.all.characters.length+1; if(_status.javaScriptExtensions) toLoad+=_status.javaScriptExtensions.reduce((constructingToLoad,javaScriptExtension)=>{ const lengths=Object.values(javaScriptExtension).reduce((constructingLengths,value)=>{ if(isArray(value)) constructingLengths.push(value.length); return constructingLengths; },[]); if(!lengths.length) return constructingToLoad+1; return constructingToLoad+Math.min(...lengths); },0); const packLoaded=gnc.of(function*(){ toLoad--; if(toLoad) return; if(_status.importing){ let promises=lib.creation.array; for(const type in _status.importing){ promises.addArray(_status.importing[type]) } yield Promise.allSettled(promises); delete _status.importing; } if(_status.windowLoaded){ delete _status.windowLoaded; lib.init.onload(); } else _status.packLoaded=true; }); if(localStorage.getItem(`${lib.configprefix}playback`)){ toLoad++; lib.init.js(`${lib.assetURL}mode`,lib.config.mode,packLoaded,packLoaded); } else if((localStorage.getItem(`${lib.configprefix}directstart`)||!show_splash)&&lib.config.all.mode.includes(lib.config.mode)){ toLoad++; lib.init.js(`${lib.assetURL}mode`,lib.config.mode,packLoaded,packLoaded); } lib.init.js(`${lib.assetURL}card`,lib.config.all.cards,packLoaded,packLoaded); lib.init.js(`${lib.assetURL}character`,lib.config.all.characters,packLoaded,packLoaded); lib.init.js(`${lib.assetURL}character`,'rank',packLoaded,packLoaded); if(!_status.javaScriptExtensions) return; const loadJavaScriptExtension=(javaScriptExtension,pathArray,fileArray,onLoadArray,onErrorArray,index)=>{ if(!pathArray&&!fileArray&&!onLoadArray&&!onErrorArray){ lib.init.js(javaScriptExtension.path,javaScriptExtension.file,()=>{ if(typeof javaScriptExtension.onload=='function') javaScriptExtension.onload(); packLoaded(); },()=>{ if(typeof javaScriptExtension.onerror=='function') javaScriptExtension.onerror(); packLoaded(); }); return; } if(typeof index!='number') index=0; if(pathArray&&index>=javaScriptExtension.path.length) return; if(fileArray&&index>=javaScriptExtension.file.length) return; if(onLoadArray&&index>=javaScriptExtension.onload.length) return; if(onErrorArray&&index>=javaScriptExtension.onerror.length) return; const path=pathArray?javaScriptExtension.path[index]:javaScriptExtension.path; const file=fileArray?javaScriptExtension.file[index]:javaScriptExtension.file; const onLoad=onLoadArray?javaScriptExtension.onload[index]:javaScriptExtension.onload; const onError=onErrorArray?javaScriptExtension.onerror[index]:javaScriptExtension.onerror; const javaScriptExtensionOnLoad=()=>{ if(typeof onLoad=='function') onLoad(); loadJavaScriptExtension(javaScriptExtension,pathArray,fileArray,onLoadArray,onErrorArray,index+1); packLoaded(); },jsExtOnError=()=>{ if(typeof onError=='function') onError(); loadJavaScriptExtension(javaScriptExtension,pathArray,fileArray,onLoadArray,onErrorArray,index+1); packLoaded(); }; lib.init.js(path,file,javaScriptExtensionOnLoad,jsExtOnError); }; _status.javaScriptExtensions.forEach(javaScriptExtension=>{ const pathArray=isArray(javaScriptExtension.path); const fileArray=isArray(javaScriptExtension.file); const onLoadArray=isArray(javaScriptExtension.onLoad); const onErrorArray=isArray(javaScriptExtension.onError); loadJavaScriptExtension(javaScriptExtension,pathArray,fileArray,onLoadArray,onErrorArray); }); }; var layout=lib.config.layout; if(layout=='default'||lib.layoutfixed.indexOf(lib.config.mode)!==-1){ layout='mobile'; } if(layout=='phone'){ layout='mobile'; game.saveConfig('layout','mobile'); game.saveConfig('phonelayout',true); } game.layout=layout; if(lib.config.image_background_random){ if(_status.htmlbg){ game.saveConfig('image_background',_status.htmlbg); } else{ var list=[]; for(var i in lib.configMenu.appearence.config.image_background.item){ if(i=='default') continue; list.push(i); } game.saveConfig('image_background',list.randomGet(lib.config.image_background)); } lib.init.background(); } delete _status.htmlbg; window.game=game; lib.announce.init(); // node:path library alternative if (typeof module!="object"||typeof module.exports!="object") lib.init.js(`${lib.assetURL}game`,"path",()=>{ lib.path=window._noname_path; delete window._noname_path; },e=>{ console.log(e); }); var styleToLoad=6; var styleLoaded=gnc.of(function*(){ --styleToLoad; if(styleToLoad==0){ if(extensionlist.length&&(lib.config.mode!='connect'||show_splash)){ _status.extensionLoading=[]; let extToLoad=extensionlist.length; const extLoaded=gnc.of(function*(){ --extToLoad; if(extToLoad==0){ yield Promise.allSettled(_status.extensionLoading); delete _status.extensionLoading; loadPack(); } }); //读取扩展 var alerted=false; for(var i=0;i.framebg,#window #arena.long.mobile:not(.fewplayer) .player[data-position="0"]>.framebg{display:block;background-image:url("'+lib.assetURL+'theme/style/player/'+bstyle+'1.png")}',0); ui.css.border_stylesheet.sheet.insertRule('#window #arena.long:not(.fewplayer) .player>.framebg, #arena.oldlayout .player>.framebg{background-image:url("'+lib.assetURL+'theme/style/player/'+bstyle+'3.png")}',0); ui.css.border_stylesheet.sheet.insertRule('.player>.count{z-index: 3 !important;border-radius: 2px !important;text-align: center !important;}',0); } if(lib.config.control_style&&lib.config.control_style!='default'&&lib.config.control_style!='custom'){ var str=''; switch(lib.config.control_style){ case 'wood':str='url("'+lib.assetURL+'theme/woodden/wood.jpg")';break; case 'music':str='linear-gradient(#4b4b4b, #464646);color:white;text-shadow:black 0 0 2px';break; case 'simple':str='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4));color:white;text-shadow:black 0 0 2px';break; } if(lib.config.control_style=='wood'){ ui.css.control_stylesheet=lib.init.sheet('#window .control,#window .menubutton,#window #system>div>div,#window #system>div>.pressdown2{background-image:'+str+'}'); } else{ ui.css.control_stylesheet=lib.init.sheet('#window .control,.menubutton:not(.active):not(.highlight):not(.red):not(.blue),#window #system>div>div{background-image:'+str+'}'); } } if(lib.config.menu_style&&lib.config.menu_style!='default'&&lib.config.menu_style!='custom'){ var str=''; switch(lib.config.menu_style){ case 'wood':str='url("'+lib.assetURL+'theme/woodden/wood2.png")';break; case 'music':str='linear-gradient(#4b4b4b, #464646);color:white;text-shadow:black 0 0 2px';break; case 'simple':str='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4));color:white;text-shadow:black 0 0 2px';break; } ui.css.menu_stylesheet=lib.init.sheet('html #window>.dialog.popped,html .menu,html .menubg{background-image:'+str+'}'); } lib.config.duration=500; if(!lib.config.touchscreen){ document.addEventListener('mousewheel',ui.click.windowmousewheel,{passive:true}); document.addEventListener('mousemove',ui.click.windowmousemove); document.addEventListener('mousedown',ui.click.windowmousedown); document.addEventListener('mouseup',ui.click.windowmouseup); document.addEventListener('contextmenu',ui.click.right); } else{ document.addEventListener('touchstart',ui.click.touchconfirm); document.addEventListener('touchstart',ui.click.windowtouchstart); document.addEventListener('touchend',ui.click.windowtouchend); document.addEventListener('touchmove',ui.click.windowtouchmove); } }; var proceed2=()=>{ if(config3){ proceed(config3); } else{ config3=true; } }; ui.css={menu:lib.init.css(lib.assetURL+'layout/default','menu',function(){ ui.css.default=lib.init.css(lib.assetURL+'layout/default','layout'); proceed2(); })}; if(lib.device){ lib.init.cordovaReady=function(){ if(lib.device=='android'){ document.addEventListener("pause", function(){ if(!_status.paused2&&(typeof _status.event.isMine=='function'&&!_status.event.isMine())){ ui.click.pause(); } if(ui.backgroundMusic){ ui.backgroundMusic.pause(); } }); document.addEventListener("resume", ()=>{ if(ui.backgroundMusic) ui.backgroundMusic.play(); }); document.addEventListener("backbutton", function(){ if(ui.arena&&ui.arena.classList.contains('menupaused')){ if(window.saveNonameInput){ window.saveNonameInput(); } else{ ui.click.configMenu(); } } else if(lib.config.confirm_exit){ navigator.notification.confirm( '是否退出游戏?', function(index){ switch(index){ case 2:game.saveConfig('null');game.reload();break; case 3:navigator.app.exitApp();break; } }, '确认退出', ['取消','重新开始','退出'] ); } else{ navigator.app.exitApp(); } }); } game.download=function(url,folder,onsuccess,onerror,dev,onprogress){ if(!url.startsWith('http')){ url=get.url(dev)+url; } var fileTransfer = new FileTransfer(); folder=lib.assetURL+folder; if(onprogress){ fileTransfer.onprogress=function(progressEvent){ onprogress(progressEvent.loaded,progressEvent.total); }; } lib.config.brokenFile.add(folder); game.saveConfigValue('brokenFile'); fileTransfer.download(encodeURI(url),encodeURI(folder),function(){ lib.config.brokenFile.remove(folder); game.saveConfigValue('brokenFile'); if(onsuccess){ onsuccess(); } },onerror); }; game.readFile=function(filename,callback,onerror){ window.resolveLocalFileSystemURL(lib.assetURL,function(entry){ entry.getFile(filename,{},function(fileEntry){ fileEntry.file(function(fileToLoad){ var fileReader = new FileReader(); fileReader.onload = function(e){ callback(e.target.result); }; fileReader.readAsArrayBuffer(fileToLoad, "UTF-8"); },onerror); },onerror); },onerror); }; game.readFileAsText=function(filename,callback,onerror){ window.resolveLocalFileSystemURL(lib.assetURL,function(entry){ entry.getFile(filename,{},function(fileEntry){ fileEntry.file(function(fileToLoad){ var fileReader = new FileReader(); fileReader.onload = function(e){ callback(e.target.result); }; fileReader.readAsText(fileToLoad, "UTF-8"); },onerror); },onerror); },onerror); }; game.writeFile=function(data,path,name,callback){ game.ensureDirectory(path,function(){ if(Object.prototype.toString.call(data)=='[object File]'){ var fileReader = new FileReader(); fileReader.onload = function(e){ game.writeFile(e.target.result,path,name,callback); }; fileReader.readAsArrayBuffer(data, "UTF-8"); } else{ window.resolveLocalFileSystemURL(lib.assetURL+path,function(entry){ entry.getFile(name,{create:true},function(fileEntry){ fileEntry.createWriter(function(fileWriter){ fileWriter.onwriteend=callback; fileWriter.write(data); }); }); }); } }); }; game.removeFile=function(dir,callback){ window.resolveLocalFileSystemURL(lib.assetURL,function(entry){ entry.getFile(dir,{},function(fileEntry){ fileEntry.remove(); if(callback){ callback(); } }); }); }; game.getFileList=(dir,success,failure)=>{ var files=[],folders=[]; window.resolveLocalFileSystemURL(lib.assetURL+dir,entry=>{ var dirReader=entry.createReader(); var entries=[]; var readEntries=()=>{ dirReader.readEntries(results=>{ if(!results.length){ entries.sort(); for(var i=0;i{ const directoryList=typeof list=='string'?[list]:list.slice().reverse(),num=file?1:0,access=(entry,directory,createDirectory)=>{ if(directory.length<=num){ createDirectory(); return; } const str=directory.pop(); return new Promise((resolve,reject)=>entry.getDirectory(str,{ create:false },resolve,reject)).catch(()=>new Promise(resolve=>entry.getDirectory(str,{ create:true },resolve))).then(directoryEntry=>access(directoryEntry,directory,createDirectory)); }; return new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(lib.assetURL,rootEntry=>{ const createDirectory=()=>{ if(directoryList.length) access(rootEntry,directoryList.pop().split('/').reverse(),createDirectory); if(typeof callback=='function') callback(); resolve(); }; createDirectory(); },reject)); }; if(ui.updateUpdate){ ui.updateUpdate(); } var showbar=function(){ if(window.StatusBar){ if(lib.device=='android'){ if(lib.config.show_statusbar_android){ window.StatusBar.overlaysWebView(false); window.StatusBar.backgroundColorByName('black'); window.StatusBar.show(); } } else if(lib.device=='ios'){ if(lib.config.show_statusbar_ios!='off'&&lib.config.show_statusbar_ios!='auto'){ if(lib.config.show_statusbar_ios=='default'){ window.StatusBar.overlaysWebView(false); } else{ window.StatusBar.overlaysWebView(true); } window.StatusBar.backgroundColorByName('black'); window.StatusBar.show(); } } } } if(lib.arenaReady){ lib.arenaReady.push(showbar); } else{ showbar(); } } } else if(typeof window.require=='function'){ lib.node={ fs:require('fs'), path:require("path"), debug:function(){ require('electron').remote.getCurrentWindow().toggleDevTools(); } }; lib.path=lib.node.path; game.download=function(url,folder,onsuccess,onerror,dev,onprogress){ if(!url.startsWith('http')){ url=get.url(dev)+url; } game.ensureDirectory(folder,function(){ try{ var file = lib.node.fs.createWriteStream(__dirname+'/'+folder); } catch(e){ onerror(); } lib.config.brokenFile.add(folder); game.saveConfigValue('brokenFile'); if(!lib.node.http) lib.node.http=require('http'); if(!lib.node.https) lib.node.https=require('https'); var opts = require('url').parse(encodeURI(url)); opts.headers={'User-Agent': 'AppleWebkit'}; (url.startsWith('https')?lib.node.https:lib.node.http).get(opts, function(response) { var stream=response.pipe(file); stream.on('finish',function(){ lib.config.brokenFile.remove(folder); game.saveConfigValue('brokenFile'); if(onsuccess){ onsuccess(); } }); stream.on('error',onerror); if(onprogress){ var streamInterval=setInterval(function(){ if(stream.closed){ clearInterval(streamInterval); } else{ onprogress(stream.bytesWritten); } },200); } }); },true); }; game.readFile=function(filename,callback,onerror){ lib.node.fs.readFile(__dirname+'/'+filename,function(err,data){ if(err){ onerror(err); } else{ callback(data); } }); }; game.readFileAsText=function(filename,callback,onerror){ lib.node.fs.readFile(__dirname+'/'+filename,'utf-8',function(err,data){ if(err){ onerror(err); } else{ callback(data); } }); }; game.writeFile=function(data,path,name,callback){ game.ensureDirectory(path,function(){ if(Object.prototype.toString.call(data)=='[object File]'){ var fileReader = new FileReader(); fileReader.onload = function(e){ game.writeFile(e.target.result,path,name,callback); }; fileReader.readAsArrayBuffer(data, "UTF-8"); } else{ get.zip(function(zip){ zip.file('i',data); lib.node.fs.writeFile(__dirname+'/'+path+'/'+name,zip.files.i.asNodeBuffer(),null,callback); }); } }); }; game.removeFile=function(filename,callback){ lib.node.fs.unlink(__dirname+'/'+filename,callback||function(){}); }; game.getFileList=(dir,success,failure)=>{ var files=[],folders=[]; dir=__dirname+'/'+dir; if(typeof failure=="undefined"){ failure=err=>{ throw err; }; } else if(failure == null){ failure=()=>{}; } try{ lib.node.fs.readdir(dir,(err,filelist)=>{ if(err){ failure(err); return; } for(var i=0;i{ const directoryList=typeof list=='string'?[list]:list.slice().reverse(),number=file?1:0,access=(path,directory,createDirectory)=>{ if(directory.length<=number){ createDirectory(); return; } path+=`/${directory.pop()}`; const fullPath=`${__dirname}${path}`; return new Promise((resolve,reject)=>lib.node.fs.access(fullPath,errnoException=>{ if(errnoException) reject(); else resolve(); })).catch(()=>new Promise((resolve,reject)=>lib.node.fs.mkdir(fullPath,errnoException=>{ if(errnoException) reject(errnoException); else resolve(); }))).then(()=>access(path,directory,createDirectory),console.log); }; return new Promise(resolve=>{ const createDirectory=()=>{ if(directoryList.length) access('',directoryList.pop().split('/').reverse(),createDirectory); else{ if(typeof callback=='function') callback(); resolve(); } }; createDirectory(); }); }; if(ui.updateUpdate){ ui.updateUpdate(); } } else{ window.onbeforeunload=function(){ if(lib.config.confirm_exit&&!_status.reloading){ return '是否离开游戏?' } else{ return null; } } } lib.config=window.config; lib.configOL={}; delete window.config; let config2; if(localStorage.getItem(`${lib.configprefix}nodb`)) window.nodb=true; if(window.indexedDB&&!window.nodb) new Promise((resolve,reject)=>{ const idbOpenDBRequest=window.indexedDB.open(`${lib.configprefix}data`,4); idbOpenDBRequest.onerror=reject; idbOpenDBRequest.onsuccess=resolve; idbOpenDBRequest.onupgradeneeded=idbVersionChangeEvent=>{ const idbDatabase=idbVersionChangeEvent.target.result; if(!idbDatabase.objectStoreNames.contains('video')) idbDatabase.createObjectStore('video',{ keyPath:'time' }); if(!idbDatabase.objectStoreNames.contains('image')) idbDatabase.createObjectStore('image'); if(!idbDatabase.objectStoreNames.contains('audio')) idbDatabase.createObjectStore('audio'); if(!idbDatabase.objectStoreNames.contains('config')) idbDatabase.createObjectStore('config'); if(!idbDatabase.objectStoreNames.contains('data')) idbDatabase.createObjectStore('data'); }; }).then(event=>{ lib.db=event.target.result; return game.getDB('config'); }).then(object=>{ if(!object.storageImported){ try{ config2=JSON.parse(localStorage.getItem(`${lib.configprefix}config`)); if(!config2||typeof config2!='object') throw 'err'; } catch(err){ config2={}; } Object.keys(config2).forEach(key=>game.saveConfig(key,config2[key])); Object.keys(lib.mode).forEach(key=>{ try{ config2=JSON.parse(localStorage.getItem(`${lib.configprefix}${key}`)); if(!config2||typeof config2!='object'||get.is.empty(config2)) throw 'err'; } catch(err){ config2=false; } localStorage.removeItem(`${lib.configprefix}${key}`); if(config2) game.putDB('data',key,config2); }); game.saveConfig('storageImported',true); lib.init.background(); localStorage.removeItem(`${lib.configprefix}config`); } else config2=object; proceed(config2); }); else{ try{ config2=JSON.parse(localStorage.getItem(lib.configprefix+'config')); if(!config2||typeof config2!='object') throw 'err' } catch(err){ config2={}; localStorage.setItem(lib.configprefix+'config',JSON.stringify({})); } proceed(config2); } }, reset:function(){ if(window.inSplash) return; if(window.resetExtension){ if(confirm('游戏似乎未正常载入,有可能因为部分扩展未正常载入,或者因为部分扩展未载入完毕。\n是否禁用扩展并重新打开?')){ window.resetExtension(); window.location.reload(); } } else{ if(lib.device){ if(navigator.notification){ navigator.notification.confirm( '游戏似乎未正常载入,是否重置游戏?', function(index){ if(index==2){ localStorage.removeItem('noname_inited'); window.location.reload(); } else if(index==3){ var noname_inited=localStorage.getItem('noname_inited'); var onlineKey=localStorage.getItem(lib.configprefix+'key'); localStorage.clear(); if(noname_inited){ localStorage.setItem('noname_inited',noname_inited); } if(onlineKey){ localStorage.setItem(lib.configprefix+'key',onlineKey); } if(indexedDB) indexedDB.deleteDatabase(lib.configprefix+'data'); setTimeout(function(){ window.location.reload(); },200); } }, '确认退出', ['取消','重新下载','重置设置'] ); } else{ if(confirm('游戏似乎未正常载入,是否重置游戏?')){ localStorage.removeItem('noname_inited'); window.location.reload(); } } } else{ if(confirm('游戏似乎未正常载入,是否重置游戏?')){ var onlineKey=localStorage.getItem(lib.configprefix+'key'); localStorage.clear(); if(onlineKey){ localStorage.setItem(lib.configprefix+'key',onlineKey); } if(indexedDB) indexedDB.deleteDatabase(lib.configprefix+'data'); setTimeout(function(){ window.location.reload(); },200); } } } }, //lib.onload支持传入GeneratorFunction以解决异步函数的问题 by诗笺 onload:gnc.of(function*(){ const libOnload=lib.onload; delete lib.onload; while(Array.isArray(libOnload)&&libOnload.length){ const fun=libOnload.shift(); if(typeof fun!="function") continue; yield (gnc.is.generatorFunc(fun)?gnc.of(fun):fun)(); } ui.updated(); game.documentZoom=game.deviceZoom; if(game.documentZoom!=1){ ui.updatez(); } ui.background=ui.create.div('.background'); ui.background.style.backgroundSize="cover"; ui.background.style.backgroundPosition='50% 50%'; if(lib.config.image_background&&lib.config.image_background!='default'&&!lib.config.image_background.startsWith('custom_')){ ui.background.setBackgroundImage('image/background/'+lib.config.image_background+'.jpg'); if(lib.config.image_background_blur){ ui.background.style.filter='blur(8px)'; ui.background.style.webkitFilter='blur(8px)'; ui.background.style.transform='scale(1.05)'; } } document.documentElement.style.backgroundImage=''; document.documentElement.style.backgroundSize=''; document.documentElement.style.backgroundPosition=''; document.body.insertBefore(ui.background,document.body.firstChild); document.body.onresize=ui.updatexr; if(lib.config.touchscreen){ document.body.addEventListener('touchstart',function(e){ this.startX=e.touches[0].clientX/game.documentZoom; this.startY=e.touches[0].clientY/game.documentZoom; _status.dragged=false; }); document.body.addEventListener('touchmove',function(e){ if(_status.dragged) return; if (Math.abs(e.touches[0].clientX/game.documentZoom - this.startX) > 10 || Math.abs(e.touches[0].clientY/game.documentZoom - this.startY) > 10) { _status.dragged=true; } }); } if(lib.config.image_background.startsWith('custom_')){ ui.background.style.backgroundImage="none"; game.getDB('image',lib.config.image_background,function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent) { var data = fileLoadedEvent.target.result; ui.background.style.backgroundImage='url('+data+')'; if(lib.config.image_background_blur){ ui.background.style.filter='blur(8px)'; ui.background.style.webkitFilter='blur(8px)'; ui.background.style.transform='scale(1.05)'; } }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.card_style=='custom'){ game.getDB('image','card_style',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.card_stylesheet){ ui.css.card_stylesheet.remove(); } ui.css.card_stylesheet=lib.init.sheet('.card:not(*:empty){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.cardback_style=='custom'){ game.getDB('image','cardback_style',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.cardback_stylesheet){ ui.css.cardback_stylesheet.remove(); } ui.css.cardback_stylesheet=lib.init.sheet('.card:empty,.card.infohidden{background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','cardback_style2',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.cardback_stylesheet2){ ui.css.cardback_stylesheet2.remove(); } ui.css.cardback_stylesheet2=lib.init.sheet('.card.infohidden:not(.infoflip){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.hp_style=='custom'){ game.getDB('image','hp_style1',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet1){ ui.css.hp_stylesheet1.remove(); } ui.css.hp_stylesheet1=lib.init.sheet('.hp:not(.text):not(.actcount)[data-condition="high"]>div:not(.lost){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','hp_style2',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet2){ ui.css.hp_stylesheet2.remove(); } ui.css.hp_stylesheet2=lib.init.sheet('.hp:not(.text):not(.actcount)[data-condition="mid"]>div:not(.lost){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','hp_style3',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet3){ ui.css.hp_stylesheet3.remove(); } ui.css.hp_stylesheet3=lib.init.sheet('.hp:not(.text):not(.actcount)[data-condition="low"]>div:not(.lost){background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); game.getDB('image','hp_style4',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.hp_stylesheet4){ ui.css.hp_stylesheet4.remove(); } ui.css.hp_stylesheet4=lib.init.sheet('.hp:not(.text):not(.actcount)>.lost{background-image:url('+fileLoadedEvent.target.result+')}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.player_style=='custom'){ ui.css.player_stylesheet=lib.init.sheet('#window .player{background-image:none;background-size:100% 100%;}'); game.getDB('image','player_style',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.player_stylesheet){ ui.css.player_stylesheet.remove(); } ui.css.player_stylesheet=lib.init.sheet('#window .player{background-image:url("'+fileLoadedEvent.target.result+'");background-size:100% 100%;}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.border_style=='custom'){ game.getDB('image','border_style',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.border_stylesheet){ ui.css.border_stylesheet.remove(); } ui.css.border_stylesheet=lib.init.sheet(); ui.css.border_stylesheet.sheet.insertRule('#window .player>.framebg{display:block;background-image:url("'+fileLoadedEvent.target.result+'")}',0); ui.css.border_stylesheet.sheet.insertRule('.player>.count{z-index: 3 !important;border-radius: 2px !important;text-align: center !important;}',0); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.control_style=='custom'){ game.getDB('image','control_style',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.control_stylesheet){ ui.css.control_stylesheet.remove(); } ui.css.control_stylesheet=lib.init.sheet('#window .control,.menubutton:not(.active):not(.highlight):not(.red):not(.blue),#window #system>div>div{background-image:url("'+fileLoadedEvent.target.result+'")}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } if(lib.config.menu_style=='custom'){ game.getDB('image','menu_style',function(fileToLoad){ if(!fileToLoad) return; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent){ if(ui.css.menu_stylesheet){ ui.css.menu_stylesheet.remove(); } ui.css.menu_stylesheet=lib.init.sheet('html #window>.dialog.popped,html .menu,html .menubg{background-image:url("'+fileLoadedEvent.target.result+'");background-size:cover}'); }; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } var proceed2=gnc.of(function*(){ var mode=lib.imported.mode; var card=lib.imported.card; var character=lib.imported.character; var play=lib.imported.play; delete window.game; var i,j,k; for(i in mode[lib.config.mode].element){ if(!lib.element[i]) lib.element[i]=[]; for(j in mode[lib.config.mode].element[i]){ if(j=='init'){ if(!lib.element[i].inits) lib.element[i].inits=[]; lib.element[i].inits.push(mode[lib.config.mode].element[i][j]); } else{ lib.element[i][j]=mode[lib.config.mode].element[i][j]; } } } for(i in mode[lib.config.mode].ai){ if(typeof mode[lib.config.mode].ai[i]=='object'){ if(ai[i]==undefined) ai[i]={}; for(j in mode[lib.config.mode].ai[i]){ ai[i][j]=mode[lib.config.mode].ai[i][j]; } } else{ ai[i]=mode[lib.config.mode].ai[i]; } } for(i in mode[lib.config.mode].ui){ if(typeof mode[lib.config.mode].ui[i]=='object'){ if(ui[i]==undefined) ui[i]={}; for(j in mode[lib.config.mode].ui[i]){ ui[i][j]=mode[lib.config.mode].ui[i][j]; } } else{ ui[i]=mode[lib.config.mode].ui[i]; } } for(i in mode[lib.config.mode].game){ game[i]=mode[lib.config.mode].game[i]; } for(i in mode[lib.config.mode].get){ get[i]=mode[lib.config.mode].get[i]; } lib.init.start=mode[lib.config.mode].start; lib.init.startBefore=mode[lib.config.mode].startBefore; if(game.onwash){ lib.onwash.push(game.onwash); delete game.onwash; } if(game.onover){ lib.onover.push(game.onover); delete game.onover; } lib.config.banned=lib.config[lib.config.mode+'_banned']||[]; lib.config.bannedcards=lib.config[lib.config.mode+'_bannedcards']||[]; lib.rank=window.noname_character_rank; delete window.noname_character_rank; for(i in mode[lib.config.mode]){ if(i=='element') continue; if(i=='game') continue; if(i=='ai') continue; if(i=='ui') continue; if(i=='get') continue; if(i=='config') continue; if(i=='onreinit') continue; if(i=='start') continue; if(i=='startBefore') continue; if(lib[i]==undefined) lib[i]=(Array.isArray(mode[lib.config.mode][i]))?[]:{}; for(j in mode[lib.config.mode][i]){ lib[i][j]=mode[lib.config.mode][i][j]; } } if(typeof mode[lib.config.mode].init=='function'){ mode[lib.config.mode].init(); } var connectCharacterPack=[]; var connectCardPack=[]; for(i in character){ if(character[i].character){ const characterPack=lib.characterPack[i]; if(characterPack) Object.assign(characterPack,character[i].character); else lib.characterPack[i]=character[i].character; } for(j in character[i]){ if(j=='mode'||j=='forbid') continue; if(j=='connect'){ connectCharacterPack.push(i); continue; } if(j=='character'&&!lib.config.characters.contains(i)&&lib.config.mode!='connect'){ if(lib.config.mode=='chess'&&get.config('chess_mode')=='leader'&&get.config('chess_leader_allcharacter')){ for(k in character[i][j]){ lib.hiddenCharacters.push(k); } } else if(lib.config.mode!='boss'||i!='boss'){ continue; } } if(Array.isArray(lib[j])&&Array.isArray(character[i][j])){ lib[j].addArray(character[i][j]); continue; } for(k in character[i][j]){ if(j=='character'){ if(!character[i][j][k][4]){ character[i][j][k][4]=[]; } if(character[i][j][k][4].contains('boss')|| character[i][j][k][4].contains('hiddenboss')){ lib.config.forbidai.add(k); } if(lib.config.forbidai_user&&lib.config.forbidai_user.contains(k)){ lib.config.forbidai.add(k); } for(var l=0;l{ const style=document.createElement("link"); style.rel="stylesheet"; if(path){ if(path[path.length-1]=='/') path=path.slice(0,path.length-1); if(file) path=`${path}${/^db:extension-[^:]*$/.test(path)?':':'/'}${file}.css`; (path.startsWith('db:')?game.getDB('image',path.slice(3)).then(get.objectURL):new Promise(resolve=>resolve(path))).then(resolvedPath=>{ style.href=resolvedPath; if(typeof before=='function'){ style.addEventListener('load',before); document.head.appendChild(style); } else if(before) document.head.insertBefore(style,before); else document.head.appendChild(style); }); } return style; }, //在扩展的precontent中调用,用于加载扩展必需的JS文件。 //If any of the parameters is an Array, corresponding files will be loaded in order //如果任意参数为数组,则按顺序加载加载相应的文件 jsForExtension:(path,file,onLoad,onError)=>{ if(!_status.javaScriptExtensions) _status.javaScriptExtensions=[]; _status.javaScriptExtensions.push({ path:path, file:file, onLoad:onLoad, onError:onError }); }, js:(path,file,onLoad,onError)=>{ if(path[path.length-1]=='/') path=path.slice(0,path.length-1); if(path==`${lib.assetURL}mode`&&lib.config.all.stockmode.indexOf(file)==-1){ lib.genAwait(lib.init[`setMode_${file}`]()).then(onLoad); return; } if(Array.isArray(file)){ file.forEach(value=>lib.init.js(path,value,onLoad,onError)); return; } let scriptSource=file?`${path}${/^db:extension-[^:]*$/.test(path)?':':'/'}${file}.js`:path; if(path.startsWith('http')) scriptSource+=`?rand=${get.id()}`; else if(lib.config.fuck_sojson&&scriptSource.includes('extension')!=-1&&scriptSource.startsWith(lib.assetURL)){ const pathToRead=scriptSource.slice(lib.assetURL.length); const alertMessage=`检测到您安装了使用免费版sojson进行加密的扩展。请谨慎使用这些扩展,避免游戏数据遭到破坏。\n扩展文件:${pathToRead}`; if(typeof game.readFileAsText=='function') game.readFileAsText(pathToRead,result=>{ if(result.includes('sojson')||result.includes('jsjiami')||result.includes('var _0x')) alert(alertMessage); },()=>void 0); else if(location.origin!='file://') lib.init.reqSync(pathToRead,function(){ const result = this.responseText; if(result.includes('sojson')||result.includes('jsjiami')||result.includes('var _0x')) alert(alertMessage); },()=>void 0); } const script=document.createElement('script'); (scriptSource.startsWith('db:')?game.getDB('image',scriptSource.slice(3)).then(get.objectURL):new Promise(resolve=>resolve(scriptSource))).then(resolvedScriptSource=>{ script.src=resolvedScriptSource; if(path.startsWith('http')) script.addEventListener('load',()=>script.remove()); document.head.appendChild(script); if(typeof onLoad=='function') script.addEventListener('load',onLoad); if(typeof onError=='function') script.addEventListener('error',onError); }); return script; }, /** * 同步lib.init.js * @returns { void } */ jsSync:(path,file,onLoad,onError)=>{ if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){ const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api'); if(typeof onError=='function') onError(e); else throw e; return; } if(path[path.length-1]=='/') path=path.slice(0,path.length-1); if(path==`${lib.assetURL}mode`&&lib.config.all.stockmode.indexOf(file)==-1){ lib.genAwait(lib.init[`setMode_${file}`]()).then(onLoad); return; } if(Array.isArray(file)){ return file.forEach(value=>lib.init.js(path,value,onLoad,onError)); } let scriptSource; if(!file) scriptSource=path; else scriptSource=`${path}/${file}.js`; if(path.startsWith('http')) scriptSource+=`?rand=${get.id()}`; const xmlHttpRequest=new XMLHttpRequest(); let data; xmlHttpRequest.addEventListener("load",()=>{ data=xmlHttpRequest.responseText; if(!data) { if(typeof onError=='function') onError(new Error(`${scriptSource}加载失败!`)); return; } if(lib.config.fuck_sojson&&scriptSource.includes('extension')!=-1&&scriptSource.startsWith(lib.assetURL)){ const pathToRead=scriptSource.slice(lib.assetURL.length); if(data.includes('sojson')||data.includes('jsjiami')||data.includes('var _0x')) alert(`检测到您安装了使用免费版sojson进行加密的扩展。请谨慎使用这些扩展,避免游戏数据遭到破坏。\n扩展文件:${pathToRead}`); } try{ window.eval(data); if(typeof onLoad=='function') onLoad(); } catch(error){ if(typeof onError=='function') onError(error); } }); if(typeof onError=='function') xmlHttpRequest.addEventListener("error",onError); xmlHttpRequest.open("GET",scriptSource,false); xmlHttpRequest.send(); }, req:(str,onload,onerror,master)=>{ let sScriptURL; if(str.startsWith('http')) sScriptURL=str; else if(str.startsWith('local:')){ if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){ const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api'); if(typeof onerror=='function') onerror(e); else throw e; return; } sScriptURL=lib.assetURL+str.slice(6); } else{ let url=get.url(master); if(url[url.length-1]!='/') url+='/'; sScriptURL=url+str; } const oReq=new XMLHttpRequest(); if(typeof onload=='function') oReq.addEventListener("load",onload); if(typeof onerror=='function') oReq.addEventListener("error",onerror); oReq.open("GET",sScriptURL); oReq.send(); }, /** * 同步lib.init.req */ reqSync:(str,onload,onerror,master)=>{ let sScriptURL; if(str.startsWith('http')) sScriptURL=str; else if(str.startsWith('local:')){ if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){ const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api'); if(typeof onerror=='function') onerror(e); else throw e; return; } sScriptURL=lib.assetURL+str.slice(6); } else{ let url=get.url(master); if(url[url.length-1]!='/')url+='/'; sScriptURL=url+str; } const oReq=new XMLHttpRequest(); if(typeof onload=='function') oReq.addEventListener("load",onload); if(typeof onerror=='function') oReq.addEventListener("error",onerror); oReq.open("GET",sScriptURL,false); oReq.send(); if(typeof onload!=='function') return oReq.responseText; }, json:(url,onload,onerror)=>{ const oReq=new XMLHttpRequest(); if(typeof onload=='function') oReq.addEventListener("load",()=>{ let result; try{ result=JSON.parse(oReq.responseText); if(!result) throw('err'); } catch(e){ if(typeof onerror=='function') onerror(e); return; } onload(result); }); if(typeof onerror=='function') oReq.addEventListener("error",onerror); oReq.open("GET",url); oReq.send(); }, /** * 同步lib.init.json */ jsonSync:(url,onload,onerror)=>{ if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){ const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api'); if(typeof onerror=='function') onerror(e); else throw e; return; } const oReq=new XMLHttpRequest(); if(typeof onload=='function') oReq.addEventListener("load",()=>{ let result; try{ result=JSON.parse(oReq.responseText); if(!result) throw('err'); } catch(e){ if(typeof onerror=='function') onerror(e); return; } onload(result); }); if(typeof onerror=='function') oReq.addEventListener("error",onerror); oReq.open("GET",url,false); oReq.send(); }, cssstyles:function(){ if(ui.css.styles){ ui.css.styles.remove(); } ui.css.styles=lib.init.sheet(); ui.css.styles.sheet.insertRule('#arena .player>.name,#arena .button.character>.name {font-family: '+(lib.config.name_font||'xinwei')+',xinwei}',0); ui.css.styles.sheet.insertRule('#arena .player>.name,.button.character>.name {font-family: '+(lib.config.name_font||'xinwei')+',xinwei}',0); ui.css.styles.sheet.insertRule('#arena .player .identity>div {font-family: '+(lib.config.identity_font||'huangcao')+',xinwei}',0); ui.css.styles.sheet.insertRule('.button.character.newstyle>.identity {font-family: '+(lib.config.identity_font||'huangcao')+',xinwei}',0); if(lib.config.cardtext_font&&lib.config.cardtext_font!='default'){ ui.css.styles.sheet.insertRule('.card div:not(.info):not(.background) {font-family: '+lib.config.cardtext_font+';}',0); } if(lib.config.global_font&&lib.config.global_font!='default'){ ui.css.styles.sheet.insertRule('#window {font-family: '+lib.config.global_font+',xinwei}',0); ui.css.styles.sheet.insertRule('#window #control{font-family: STHeiti,SimHei,Microsoft JhengHei,Microsoft YaHei,WenQuanYi Micro Hei,Suits,Helvetica,Arial,sans-serif}',0); } switch(lib.config.glow_phase){ case 'yellow':ui.css.styles.sheet.insertRule('#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgb(217, 152, 62) 0 0 15px, rgb(217, 152, 62) 0 0 15px !important;}',0);break; case 'green':ui.css.styles.sheet.insertRule('#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgba(10, 155, 67, 1) 0 0 15px, rgba(10, 155, 67, 1) 0 0 15px !important;}',0);break; case 'purple':ui.css.styles.sheet.insertRule('#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgb(189, 62, 170) 0 0 15px, rgb(189, 62, 170) 0 0 15px !important;}',0);break; } }, layout:function(layout,nosave){ const loadingScreen=ui.create.div('.loading-screen',document.body),loadingScreenStyle=loadingScreen.style; loadingScreenStyle.animationDuration='1s'; loadingScreenStyle.animationFillMode='forwards'; loadingScreenStyle.animationName='opacity-0-1'; if(layout=='default') layout='mobile'; if(!nosave) game.saveConfig('layout',layout); game.layout=layout; ui.arena.hide(); new Promise(resolve=>setTimeout(resolve,500)).then(()=>{ if(game.layout=='default'){ ui.css.layout.href=''; } else{ ui.css.layout.href=lib.assetURL+'layout/'+game.layout+'/layout.css'; } if(game.layout=='mobile'||game.layout=='long'){ ui.arena.classList.add('mobile'); } else{ ui.arena.classList.remove('mobile'); } if(game.layout=='mobile'||game.layout=='long'||game.layout=='long2'||game.layout=='nova'){ if(game.me&&game.me.node.handcards2.childNodes.length){ while(game.me.node.handcards2.childNodes.length){ game.me.node.handcards1.appendChild(game.me.node.handcards2.firstChild); } } } if(game.layout=='default'){ ui.arena.classList.add('oldlayout'); } else{ ui.arena.classList.remove('oldlayout'); } if(lib.config.cardshape=='oblong'&&(game.layout=='long'||game.layout=='mobile'||game.layout=='long2'||game.layout=='nova')){ ui.arena.classList.add('oblongcard'); ui.window.classList.add('oblongcard'); } else{ ui.arena.classList.remove('oblongcard'); ui.window.classList.remove('oblongcard'); } //if(lib.config.textequip=='text'&&(game.layout=='long'||game.layout=='mobile')){ if(game.layout=='long'||game.layout=='mobile'){ ui.arena.classList.add('textequip'); } else{ ui.arena.classList.remove('textequip'); } if(get.is.phoneLayout()){ ui.css.phone.href=lib.assetURL+'layout/default/phone.css'; ui.arena.classList.add('phone'); } else{ ui.css.phone.href=''; ui.arena.classList.remove('phone'); } for(var i=0;isetTimeout(resolve,100)); }).then(()=>{ ui.arena.show(); if(game.me) game.me.update(); return new Promise(resolve=>setTimeout(resolve,500)); }).then(()=>{ ui.updatex(); ui.updatePlayerPositions(); return new Promise(resolve=>setTimeout(resolve,500)); }).then(()=>{ ui.updatec(); loadingScreenStyle.animationName='opacity-1-0'; loadingScreen.addEventListener('animationend',animationEvent=>animationEvent.target.remove()); }); }, background:function(){ if(lib.config.image_background_random){ var list=[]; for(var i in lib.configMenu.appearence.config.image_background.item){ if(i=='default') continue; list.push(i); } list.remove(lib.config.image_background); localStorage.setItem(lib.configprefix+'background',JSON.stringify(list)); } else if(lib.config.image_background&&lib.config.image_background!='default'&&!lib.config.image_background.startsWith('custom_')){ localStorage.setItem(lib.configprefix+'background',lib.config.image_background); } else if(lib.config.image_background=='default'&&lib.config.theme=='simple'){ localStorage.setItem(lib.configprefix+'background','ol_bg'); } else{ localStorage.removeItem(lib.configprefix+'background'); } }, parsex:function(item){ //by 诗笺、Tipx-L /** * @param {Function} func */ function Legacy(func){ //Remove all comments //移除所有注释 let str=func.toString().replace(/((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|(?:\r?\n|[\s\S])[^\/"'\\\s]*)/mg,'$2').trim(); //获取第一个 { 后的所有字符 str=str.slice(str.indexOf('{')+1); //判断代码中是否有debugger let regex=/event\.debugger\(\)/; let hasDebugger=false; let insertDebugger=`yield code=>eval(code);`; let debuggerSkip=0; let debuggerResult; while((debuggerResult=str.slice(debuggerSkip).match(regex))!=null){ let debuggerCopy=str; debuggerCopy=debuggerCopy.slice(0,debuggerSkip+debuggerResult.index)+insertDebugger+debuggerCopy.slice(debuggerSkip+debuggerResult.index+debuggerResult[0].length,-1); //测试是否有错误 try { new GeneratorFunction(debuggerCopy); str=debuggerCopy+'}'; debuggerSkip+=debuggerResult.index+insertDebugger.length; hasDebugger=true; }catch(error){ debuggerSkip+=debuggerResult.index+debuggerResult[0].length; } } //func中要写步骤的话,必须要写step 0 if(str.indexOf('step 0')==-1){ str='{if(event.step==1) {event.finish();return;}\n'+str; }else{ let skip=0; let k=0; let result; //去除99个step的限制 while((result=str.slice(skip).match(new RegExp(`['"]step ${k}['"]`)))!=null){ let insertStr; if(k==0){ insertStr=`switch(step){case 0:`; }else{ insertStr=`break;case ${k}:`; } let copy=str; copy=copy.slice(0,skip+result.index)+insertStr+copy.slice(skip+result.index+result[0].length); //测试是否有错误 try{ new (hasDebugger?GeneratorFunction:Function)(copy); str=copy; skip+=result.index+insertStr.length; }catch(error){ k--; skip+=result.index+result[0].length; } k++; } str=`if(event.step==${k}){event.finish();return;}`+str; } return (new (hasDebugger?GeneratorFunction:Function)('event','step','source','player','target','targets', 'card','cards','skill','forced','num','trigger','result', '_status','lib','game','ui','get','ai',str)); } switch(typeof item){ case "object": if(Array.isArray(item)){ let lastEvent=null; return function*(event,step,source,player,target,targets,card,cards,skill,forced,num,trigger,result,_status,lib,game,ui,get,ai){ if(step>=item.length) return event.finish(); var current=item[step]; if(typeof current!="function") throw new Error(`content ${step} of ${event.name} is not vaild: ${current}`); var currentResult=current(event,{ event:event, step:step, source:source, player:player, target:target, targets:targets, card:card, cards:cards, skill:skill, forced:forced, num:num, trigger:trigger, result:result },(lastEvent&&("result" in lastEvent))?lastEvent.result:null); // TODO: use `event.debugger` to replace source if(gnc.is.generator(currentResult)) lastEvent=yield* currentResult; else lastEvent=currentResult; } } else{ if(Symbol.iterator in item) return lib.init.parsex(Array.from(item)); if(item.toString !== Object.prototype.toString) return lib.init.parsex(item.toString()); if("render" in item) { // TODO: Object Render Parse throw new Error("NYI: Object Render Parse"); } // TODO: Object Other Parse throw new Error("NYI: Object Other Parse"); } case "function": if (gnc.is.generatorFunc(item)) { let gen,lastEvent; return function*(event,step,source,player,target,targets,card,cards,skill,forced,num,trigger,result,_status,lib,game,ui,get,ai){ event.step=NaN; if(!gen)gen=item(event,{ event:event, step:step, source:source, player:player, target:target, targets:targets, card:card, cards:cards, skill:skill, forced:forced, num:num, trigger:trigger, result:result }); var res=gen.next((lastEvent&&("result" in lastEvent))?lastEvent.result:null); if(res.done) event.finish(); else { var currentResult=res.value; // TODO: use `event.debugger` to replace source if(typeof currentResult=="function") yield currentResult; else lastEvent=currentResult; } } } default: return Legacy(item); } }, eval:function(func){ if(typeof func=='function'){ return eval('('+func.toString()+')'); } else if(typeof func=='object'){ for(var i in func){ if(func.hasOwnProperty(i)){ func[i]=lib.init.eval(func[i]); } } } return func; }, encode:function(strUni){ var strUtf = strUni.replace( /[\u0080-\u07ff]/g,function(c){ var cc = c.charCodeAt(0); return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }); strUtf = strUtf.replace( /[\u0800-\uffff]/g,function(c) { var cc = c.charCodeAt(0); return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }); return btoa(strUtf); }, decode:function(str){ var strUtf=atob(str); var strUni = strUtf.replace( /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,function(c) { var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f); return String.fromCharCode(cc); }); strUni = strUni.replace( /[\u00c0-\u00df][\u0080-\u00bf]/g,function(c){ var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; return String.fromCharCode(cc); }); return strUni; }, stringify:function(obj){ var str='{' for(var i in obj){ str+='"'+i+'":' if(Object.prototype.toString.call(obj[i])=='[object Object]'){ str+=lib.init.stringify(obj[i]); } else if(typeof obj[i]=='function'){ str+=obj[i].toString(); } else{ str+=JSON.stringify(obj[i]); } str+=',' } str+='}'; return str; }, stringifySkill:function(obj){ var str=''; for(var i in obj){ str+=i+':' if(Object.prototype.toString.call(obj[i])=='[object Object]'){ str+='{\n'+lib.init.stringifySkill(obj[i])+'}'; } else if(typeof obj[i]=='function'){ str+=obj[i].toString().replace(/\t/g,''); } else{ str+=JSON.stringify(obj[i]); } str+=',\n' } return str; } }, cheat:{ i:function(){ window.cheat=lib.cheat; window.game=game; window.ui=ui; window.get=get; window.ai=ai; window.lib=lib; window._status=_status; }, dy:function(){ var next=game.me.next; for(var i=0;i<10;i++){ if(next.identity!='zhu'){ break; } next=next.next; } next.die(); }, x:function(){ var gl=function(dir,callback){ var files=[],folders=[]; dir='/Users/widget/Documents/extension/'+dir; lib.node.fs.readdir(dir,function(err,filelist){ for(var i=0;i1){ for(var i=0;i{ if(!lib.config.forbidai.includes(key)&&!key.startsWith('boss_')&&!key.startsWith('tafang_')&&!list.includes(key)) console.log(get.translation(key),key); }); }, h:function(player){ console.log(get.translation(player.getCards('h'))); }, g:function(){ for(var i=0;i0&&typeof arguments[i]=='number'){ for(var j=0;j{ var hs=player.getCards('h'),showingCards=event._cards.filter(showingCard=>hs.includes(showingCard)),shown=player.getShownCards(); event.gaintag.forEach(tag=>player.addGaintag(showingCards,tag)); if(!(event.cards=showingCards.filter(showingCard=>!shown.includes(showingCard))).length) return; game.log(player,'明置了',event.cards); if(event.animate!=false) player.$give(event.cards,player,false); event.trigger('addShownCardsAfter'); }, //隐藏明置手牌 hideShownCards:()=>{ var shown=player.getShownCards(),hidingCards=event._cards.filter(hidingCard=>shown.includes(hidingCard)); if(!hidingCards.length) return; if(event.gaintag.length) event.gaintag.forEach(tag=>player.removeGaintag(tag,hidingCards)); else { var map=hidingCards.reduce((constructingMap,hidingCard)=>{ hidingCard.gaintag.forEach(tag=>{ if(!tag.startsWith('visible_')) return; if(!constructingMap[tag]) constructingMap[tag]=[]; constructingMap[tag].push(hidingCard); }); return constructingMap; },{}); Object.keys(map).forEach(key=>player.removeGaintag(key,map[key])); } hidingCards.removeArray(player.getShownCards()); if(!hidingCards.length) return; game.log(player,'取消明置了',event.cards=hidingCards); if(event.animate!=false) player.$give(hidingCards,player,false); event.trigger('hideShownCardsAfter'); }, //Execute the delay card effect //执行延时锦囊牌效果 executeDelayCardEffect:()=>{ 'step 0' target.$phaseJudge(card); event.cancelled=false; event.trigger('executeDelayCardEffect'); event.cardName=card.viewAs||card.name; target.popup(event.cardName,'thunder'); if(!lib.card[event.cardName].effect){ game.delay(); event.finish(); } else if(!lib.card[event.cardName].judge){ game.delay(); event.nojudge=true; } 'step 1' if(event.cancelled||event.nojudge) return; var next=player.judge(card),judge=event.judge; if(typeof judge=='function') next.judge=judge; var judge2=event.judge2; if(typeof judge2=='function') next.judge2=judge2; 'step 2' if(event.excluded) delete event.excluded; else{ var cardName=event.cardName; if(event.cancelled&&!event.direct){ var cardCancel=lib.card[cardName].cancel; if(cardCancel){ var next=game.createEvent(`${cardName}Cancel`); next.setContent(cardCancel); next.cards=[card]; if(!card.viewAs){ var autoViewAs=next.card=get.autoViewAs(card); autoViewAs.expired=card.expired; } else{ var autoViewAs=next.card=get.autoViewAs({ name:cardName },next.cards); autoViewAs.expired=card.expired; } next.player=player; } } else{ var next=game.createEvent(cardName); next.setContent(lib.card[cardName].effect); next._result=result; next.cards=[card]; if(!card.viewAs){ var autoViewAs=next.card=get.autoViewAs(card); autoViewAs.expired=card.expired; } else{ var autoViewAs=next.card=get.autoViewAs({ name:cardName },next.cards); autoViewAs.expired=card.expired; } next.player=player; } } ui.clear(); card.delete(); }, //Gift //赠予 gift:()=>{ 'step 0' event.num=0; 'step 1' if(num{ 'step 0' game.log(player,'重铸了',cards); if(typeof event.recastingLose!='function') return; event.trigger('recastingLose'); event.recastingLose(player,cards); event.trigger('recastingLost'); event.recastingLosingEvents.push(...event.next.filter(value=>value.name!='arrangeTrigger')); 'step 1' event.trigger('recast'); 'step 2' if(typeof event.recastingGain!='function') return; event.trigger('recastingGain'); event.recastingGain(player,cards); event.trigger('recastingGained'); event.recastingGainingEvents.push(...event.next.filter(value=>value.name!='arrangeTrigger')); }, //装备栏相关 disableEquip:function(){ 'step 0' event.cards=[]; event.num=0; event.slotsx=[]; if(get.is.mountCombined()){ event.slots.forEach(type=>{ if(type=='equip3'||type=='equip4') event.slotsx.add('equip3_4'); else event.slotsx.add(type) }); } else{ event.slotsx.addArray(event.slots); } event.slotsx.sort(); if(!event.slots.length) event.finish(); 'step 1' var slot=event.slotsx[event.num]; var slot_key=slot; var left=player.countEnabledSlot(slot),lose; if(slot=='equip3_4'){ lose=Math.min(left,Math.max(get.numOf(event.slots,'equip3'),get.numOf(event.slots,'equip4'))); slot_key='equip3'; } else lose=Math.min(left,get.numOf(event.slots,slot)); if(lose<=0) event.goto(3); else{ game.log(player,'废除了'+get.cnNumber(lose)+'个','#g'+get.translation(slot)+'栏'); if(!player.disabledSlots) player.disabledSlots={}; if(!player.disabledSlots[slot_key]) player.disabledSlots[slot_key]=0; player.disabledSlots[slot_key]+=lose; var cards=player.getEquips(slot).filter(card=>!event.cards.contains(card)); if(cards.length>0){ if(lose>=left){ event._result={bool:true,links:cards}; } else if(cards.length>(left-lose)){ var source=event.source,num=(cards.length-(left-lose)); if(!source||!source.isIn()) source=player; source.chooseButton([ '选择'+(player==source?'你':get.translation(player))+'的'+get.cnNumber(num)+'张'+get.translation(slot)+'牌置入弃牌堆', cards, ],true,[1,num]).set('filterOk',function(){ var evt=_status.event; return ui.selected.buttons.reduce(function(num,button){ if(evt.slot=='equip3_4') return num+Math.max(get.numOf(get.subtypes(button.link,false),'equip3'),get.numOf(get.subtypes(button.link,false),'equip4')); return num+get.numOf(get.subtypes(button.link,false),evt.slot) },0)==evt.required; }).set('required',num).set('slot',slot) } else event.goto(3); } else event.goto(3) } 'step 2' if(result.bool) event.cards.addArray(result.links); 'step 3' event.num++; if(event.num0) player.loseToDiscardpile(cards); } }, enableEquip:function(){ if(!event.slots.length) return; var slotsx=[...new Set(event.slots)].sort(); for(var slot of slotsx){ var lost=player.countDisabledSlot(slot),gain=Math.min(lost,get.numOf(event.slots,slot)); if(lost<=0) continue; else{ game.log(player,'恢复了'+get.cnNumber(gain)+'个','#g'+get.translation(slot)+'栏'); if(!player.disabledSlots) player.disabledSlots={}; if(!player.disabledSlots[slot]) player.disabledSlots[slot]=0; player.disabledSlots[slot]-=gain; } } player.$syncDisable(); }, expandEquip:function(){ if(!event.slots.length) return; var slotsx=[]; if(get.is.mountCombined()){ event.slots.forEach(type=>{ if(type=='equip3'||type=='equip4') slotsx.add('equip3_4'); else slotsx.add(type) }); } else{ slotsx.addArray(event.slots); } slotsx.sort(); for(var slot of slotsx){ var expand=get.numOf(event.slots,slot),slot_key=slot; if(slot=='equip3_4'){ expand=Math.max(get.numOf(event.slots,'equip3'),get.numOf(event.slots,'equip4')); slot_key='equip3'; } game.log(player,'获得了'+get.cnNumber(expand)+'个额外的','#g'+get.translation(slot)+'栏'); if(!player.expandedSlots) player.expandedSlots={}; if(!player.expandedSlots[slot_key]) player.expandedSlots[slot_key]=0; player.expandedSlots[slot_key]+=expand; } player.$syncExpand(); }, //选择顶装备要顶的牌 replaceEquip:function(){ 'step 0' event.cards=[]; var types=get.subtypes(card,false); if(types.length){ var info=get.info(card,false); if(info.customSwap){ event.cards.addArray(player.getCards('e',function(card){ return info.customSwap(card); })); event.goto(4); } else{ event.num=0; event.slots=types; event.slotsx=[]; if(get.is.mountCombined()){ event.slots.forEach(type=>{ if(type=='equip3'||type=='equip4') event.slotsx.add('equip3_4'); else event.slotsx.add(type) }); } else{ event.slotsx.addArray(event.slots); } event.slotsx.sort(); } } else event.goto(4); 'step 1' var slot=event.slotsx[event.num]; var left=player.countEquipableSlot(slot),lose; if(slot=='equip3_4') lose=Math.min(left,Math.max(get.numOf(event.slots,'equip3'),get.numOf(event.slots,'equip4'))); else lose=Math.min(left,get.numOf(event.slots,slot)); if(lose<=0) event.goto(3); else{ var cards=player.getEquips(slot).filter(card=>{ return !event.cards.contains(card)&&lib.filter.canBeReplaced(card,player); }); if(cards.length>0){ if(lose>=left){ event._result={bool:true,links:cards}; } else if(cards.length>(left-lose)){ var source=event.source,num=(cards.length-(left-lose)); if(!source||!source.isIn()) source=player; source.chooseButton([ '选择替换掉'+get.cnNumber(num)+'张'+get.translation(slot)+'牌', cards, ],true,[1,num]).set('filterOk',function(){ var evt=_status.event; return ui.selected.buttons.reduce(function(num,button){ if(evt.slot=='equip3_4') return num+Math.max(get.numOf(get.subtypes(button.link,false),'equip3'),get.numOf(get.subtypes(button.link,false),'equip4')); return num+get.numOf(get.subtypes(button.link,false),evt.slot) },0)==evt.required; }).set('required',num).set('slot',slot) } else event.goto(3); } else event.goto(3) } 'step 2' if(result.bool) event.cards.addArray(result.links); 'step 3' event.num++; if(event.num0; }); if(!event.targets.length) event.result={bool:false}; else{ var next=player.chooseCardOL(event.targets,get.translation(player)+'发起了议事,请选择展示的手牌',true).set('type','debate').set('source',player).set('ai',event.ai||function(card){ return Math.random(); }).set('aiCard',event.aiCard||function(target){ var hs=target.getCards('h'); return {bool:true,cards:[hs.randomGet()]}; }); next._args.remove('glow_result'); } 'step 1' var red=[],black=[]; event.videoId=lib.status.videoId++; for(var i=0;i红色,展示了',red.map(function(i){ return i[1]; })); } else game.log('#b无人','意见为红色'); if(black.length){ game.log(black.map(function(i){ return i[0]; }),'意见为','#g黑色',',展示了',black.map(function(i){ return i[1]; })); } else game.log('#b无人','意见为','#g黑色'); game.broadcastAll(function(name,id,redArgs,blackArgs){ var dialog=ui.create.dialog(name+'发起了议事','hidden','forcebutton'); dialog.videoId=id; dialog.classList.add('scroll1'); dialog.classList.add('scroll2'); dialog.classList.add('fullwidth'); dialog.classList.add('fullheight'); dialog.buttonss=[]; var list=['意见为红色的角色','意见为黑色的角色'] for(var i=0;i'+list[i]+''); var buttons=ui.create.div('.buttons',dialog.content); dialog.buttonss.push(buttons); buttons.classList.add('popup'); buttons.classList.add('guanxing'); } var func=function(target){ if(target._tempTranslate) return target._tempTranslate; var name=target.name; if(lib.translate[name+'_ab']) return lib.translate[name+'_ab']; return get.translation(name); }; for(var i=0;ievent.black.length) opinion='red'; else if(event.red.length红色':'#g黑色'); else game.log(player,'本次发起的议事无结果'); event.result={ bool:true, opinion:opinion, red:event.red, black:event.black, targets:event.targets } 'step 3' if(event.callback){ var next=game.createEvent('debateCallback',false); next.player=player; next.debateResult=get.copy(event.result); next.setContent(event.callback); } }, delay:function(){ game[event.name].apply(game,event._args) }, chooseCooperationFor:function(){ 'step 0' var next=player.chooseButton([ '选择和'+get.translation(target)+'的协力方式', [event.cardlist,'vcard'], ],true); next.set('ai',event.ai||function(){ return Math.random(); }); 'step 1' if(result.bool){ player.cooperationWith(target,result.links[0][2].slice(12),event.reason); } }, chooseToPlayBeatmap:function(){ 'step 0' if(game.online) return; if(_status.connectMode) event.time=lib.configOL.choose_timeout; event.videoId=lib.status.videoId++; //给其他角色看的演奏框 game.broadcastAll(function(player,id,beatmap){ if(_status.connectMode) lib.configOL.choose_timeout=(Math.ceil((beatmap.timeleap[beatmap.timeleap.length-1]+beatmap.speed*100+(beatmap.current||0))/1000)+5).toString(); if(player==game.me) return; var str=get.translation(player)+'正在演奏《'+beatmap.name+'》...'; if(!_status.connectMode) str+='
        (点击屏幕可以跳过等待AI操作)'; ui.create.dialog(str).videoId=id; if(ui.backgroundMusic) ui.backgroundMusic.pause(); if(lib.config.background_audio){ if(beatmap.filename.startsWith('ext:')) game.playAudio(beatmap.filename); else game.playAudio('effect',beatmap.filename); } },player,event.videoId,event.beatmap); 'step 1' var beatmap=event.beatmap; if(event.isMine()){ var timeleap=beatmap.timeleap.slice(0); var current=beatmap.current; //获取两个音符的时间间隔 var getTimeout=function(){ var time=timeleap.shift(); var out=time-current; current=time; return out; }; //初始化一堆变量 var score=0; var added=timeleap.length; var number_of_tracks=beatmap.number_of_tracks||6; var custom_mapping=Array.isArray(beatmap.mapping); var mapping=custom_mapping?beatmap.mapping.slice():beatmap.mapping; var hitsound=beatmap.hitsound||'hitsound.wav'; if(hitsound.startsWith('ext:')) hitsound=lib.assetURL+'extension/'+hitsound.slice(4); else hitsound=lib.assetURL+'audio/effect/'+hitsound; var hitsound_audio=new Audio(hitsound); hitsound_audio.volume=0.25; var abs=1; var node_pos=0; if(custom_mapping){ node_pos=mapping.shift(); } else if(mapping=='random'){ abs=get.rand(number_of_tracks); node_pos=abs; } var combo=0; var max_combo=0; var nodes=[]; var roundmenu=false; //隐藏菜单按钮 if(ui.roundmenu&&ui.roundmenu.display!='none'){ roundmenu=true; ui.roundmenu.style.display='none'; } if(ui.backgroundMusic) ui.backgroundMusic.pause(); var event=_status.event; event.settleed=false; //建个框框 var dialog=ui.create.dialog('forcebutton','hidden'); event.dialog=dialog; event.dialog.textPrompt=event.dialog.add('
        '+(beatmap.prompt||'在音符滑条和底部判定区重合时点击屏幕!')+'
        '); event.switchToAuto=function(){}; event.dialog.classList.add('fixed'); event.dialog.classList.add('scroll1'); event.dialog.classList.add('scroll2'); event.dialog.classList.add('fullwidth'); event.dialog.classList.add('fullheight'); event.dialog.classList.add('noupdate'); event.dialog.style.overflow='hidden'; //结束后操作 event.settle=function(){ if(event.settleed) return; event.settleed=true; //评分 var acc=Math.floor(score/(added*5)*100); if(!Array.isArray(lib.config.choose_to_play_beatmap_accuracies)) lib.config.choose_to_play_beatmap_accuracies=[]; lib.config.choose_to_play_beatmap_accuracies.push(acc); if(lib.config.choose_to_play_beatmap_accuracies.length>5) lib.config.choose_to_play_beatmap_accuracies.shift(); game.saveConfigValue("choose_to_play_beatmap_accuracies"); var rank; if(acc==100) rank=['SS','metal']; else if(acc>=94) rank=['S','orange']; else if(acc>=87) rank=['A','wood']; else if(acc>=80) rank=['B','water']; else if(acc>=65) rank=['C','thunder']; else rank=['D','fire']; event.dialog.textPrompt.innerHTML='
        演奏结束!
        最大连击数:'+max_combo+' 精准度:'+acc+'%
        '; game.me.$fullscreenpop('演奏评级:'+rank[0]+'',null,null,false); //返回结果并继续游戏 setTimeout(function(){ event._result={ bool:true, accuracy:acc, rank:rank, }; event.dialog.close(); game.resume(); _status.imchoosing=false; if(roundmenu) ui.roundmenu.style.display=''; if(ui.backgroundMusic) ui.backgroundMusic.play(); hitsound_audio.remove(); },1000); }; event.dialog.open(); //操作容差 var height=event.dialog.offsetHeight; var width=event.dialog.offsetWidth; var range1=(beatmap.range1||[90,110]); var range2=(beatmap.range2||[93,107]); var range3=(beatmap.range3||[96,104]); var speed=(beatmap.speed||25); //初始化底部的条子 var judger=ui.create.div(''); judger.style["background-image"]=(beatmap.judgebar_color||'linear-gradient(rgba(240, 235, 3, 1), rgba(230, 225, 5, 1))'); judger.style["border-radius"]='3px'; judger.style.position='absolute'; judger.style.opacity='0.3'; var heightj=Math.ceil(height*(beatmap.judgebar_height||0.1)); judger.style.height=heightj+'px'; judger.style.width=width+'px'; judger.style.left='0px'; judger.style.top=(height-heightj)+'px'; event.dialog.appendChild(judger); //生成每个音符 var addNode=function(){ var node=ui.create.div(''); nodes.push(node); node.style["background-image"]=(beatmap.node_color||'linear-gradient(rgba(120, 120, 240, 1), rgba(100, 100, 230, 1))'); node.style["border-radius"]='3px'; node.style.position='absolute'; node.style.height=Math.ceil(height/10)+'px'; node.style.width=Math.ceil(width/number_of_tracks)-10+'px'; node._position=get.utc(); event.dialog.appendChild(node); node.style.left=Math.ceil(width*node_pos/number_of_tracks+5)+'px'; node.style.top='-'+(Math.ceil(height/10))+'px'; ui.refresh(node); node.style.transition='all '+speed*110+'ms linear'; node.style.transform='translateY('+Math.ceil(height*1.1)+'px)'; node.timeout=setTimeout(function(){ if(nodes.contains(node)){ nodes.remove(node); player.popup('Miss','fire',false); if(player.damagepopups.length) player.$damagepop(); combo=0; } },speed*110); if(custom_mapping){ node_pos=mapping.shift(); } else if(mapping=='random'){ while(node_pos==abs){ node_pos=get.rand(number_of_tracks); } abs=node_pos; } else{ node_pos+=abs; if(node_pos>number_of_tracks-1){ abs=-1; node_pos=number_of_tracks-2; } else if(node_pos<0){ abs=1; node_pos=1; } } if(timeleap.length){ setTimeout(function(){ addNode(); },getTimeout()); } else{ setTimeout(function(){ event.settle(); },speed*110+100) } } //点击时的判断操作 var click=function(){ if(!nodes.length) return; for(var node of nodes){ //用生成到点击的时间差来判断距离 var time=get.utc(); var top=(time-node._position)/speed; if(top>range1[1]) continue; else if(top=range3[0]&&top=range2[0]&&topvoid 0); break; } }; document.addEventListener(lib.config.touchscreen?'touchstart':'mousedown',click); game.pause(); game.countChoose(); setTimeout(()=>{ if(!lib.config.background_audio) return; if(beatmap.filename.startsWith('ext:')) game.playAudio(beatmap.filename); else game.playAudio('effect',beatmap.filename); },Math.floor(speed*100*(0.9+beatmap.judgebar_height))+beatmap.current); setTimeout(function(){ addNode(); },getTimeout()); } else if(event.isOnline()){ event.send(); } else{ game.pause(); game.countChoose(); var settle=function(){ _status.imchoosing=false; //Algorithm: Generate the random number range using the mean and the half standard deviation of accuracies of the player's last 5 plays //算法:用玩家的上5次游玩的准确率的平均数和半标准差生成随机数范围 var choose_to_play_beatmap_accuracies=(lib.config.choose_to_play_beatmap_accuracies||[]).concat(Array.from({ length:6-(lib.config.choose_to_play_beatmap_accuracies||[]).length },()=>get.rand(70,100))); var mean=Math.round(choose_to_play_beatmap_accuracies.reduce((previousValue,currentValue)=>previousValue+currentValue)/choose_to_play_beatmap_accuracies.length); var half_standard_deviation=Math.round(Math.sqrt(choose_to_play_beatmap_accuracies.reduce((previousValue,currentValue)=>previousValue+Math.pow(currentValue-mean,2),0))/2); var acc=Math.min(Math.max(get.rand.apply(get,beatmap.aiAcc||[mean-half_standard_deviation-get.rand(0,half_standard_deviation),mean+half_standard_deviation+get.rand(0,half_standard_deviation)]),0),100); var rank; if(acc==100) rank=['SS','metal']; else if(acc>=94) rank=['S','orange']; else if(acc>=87) rank=['A','green']; else if(acc>=80) rank=['B','water']; else if(acc>=65) rank=['C','thunder']; else rank=['D','fire']; event._result={ bool:true, accuracy:acc, rank:rank, }; if(event.dialog) event.dialog.close(); if(event.control) event.control.close(); game.resume(); }; var song_duration=beatmap.timeleap[beatmap.timeleap.length-1]+beatmap.speed*100+1000+(beatmap.current||0); var settle_timeout=setTimeout(settle,song_duration); if(!_status.connectMode) { var skip_timeout; var skip=()=>{ settle(); Array.from(ui.window.getElementsByTagName('audio')).forEach(audio=>{ if(audio.currentSrc.includes(beatmap.filename.startsWith('ext:')?beatmap.name:beatmap.filename)) audio.remove(); }); document.removeEventListener(lib.config.touchscreen?'touchend':'click',skip); clearTimeout(settle_timeout); clearTimeout(skip_timeout); }; document.addEventListener(lib.config.touchscreen?'touchend':'click',skip); skip_timeout=setTimeout(()=>document.removeEventListener(lib.config.touchscreen?'touchend':'click',skip),song_duration); } } 'step 2' game.broadcastAll(function(id,time){ if(_status.connectMode) lib.configOL.choose_timeout=time; var dialog=get.idDialog(id); if(dialog){ dialog.close(); } if(ui.backgroundMusic) ui.backgroundMusic.play(); },event.videoId,event.time); var result=event.result||result; event.result=result; }, chooseToMove:function(){ 'step 0' if(event.chooseTime&&_status.connectMode&&!game.online){ event.time=lib.configOL.choose_timeout; game.broadcastAll(function(time){ lib.configOL.choose_timeout=time; },event.chooseTime); } if(event.isMine()){ delete ui.selected.guanxing_button; var list=event.list,filterMove=event.filterMove,filterOk=event.filterOk; _status.imchoosing=true; var event=_status.event; event.settleed=false; event.dialog=ui.create.dialog(event.prompt||'请选择要操作的牌','hidden','forcebutton'); event.switchToAuto=function(){ if(!filterOk(event.moved)){ if(!event.forced) event._result={bool:false}; else event._result='ai'; } else{ event._result={ bool:true, moved:event.moved, }; } event.dialog.close(); if(ui.confirm) ui.confirm.close(); game.resume(); _status.imchoosing=false; setTimeout(function(){ ui.arena.classList.remove('choose-to-move'); },500); }; event.dialog.classList.add('scroll1'); event.dialog.classList.add('scroll2'); event.dialog.classList.add('fullwidth'); if(list.length>1){ ui.arena.classList.add('choose-to-move'); event.dialog.classList.add('fullheight'); } event.moved=[]; var buttonss=[]; event.buttonss=buttonss; var updateButtons=function(){ for(var i of buttonss){ event.moved[i._link]=get.links(Array.from(i.childNodes)); if(i.textPrompt) i.previousSibling.innerHTML=('
        '+i.textPrompt(event.moved[i._link])+'
        '); } if(filterOk(event.moved)){ ui.create.confirm('o'); } else{ if(!event.forced) ui.create.confirm('c'); else if(ui.confirm) ui.confirm.close(); } }; var clickButtons=function(){ if(!ui.selected.guanxing_button) return; if(ui.selected.guanxing_button.parentNode==this) return; if(!filterMove(ui.selected.guanxing_button,this._link,event.moved)) return; ui.selected.guanxing_button.classList.remove('glow2'); this.appendChild(ui.selected.guanxing_button); delete ui.selected.guanxing_button; updateButtons(); }; for(var i=0;i'+list[i][0]+''); tex.classList.add('choosetomove'); var buttons=ui.create.div('.buttons',event.dialog.content,clickButtons); buttonss.push(buttons); buttons.classList.add('popup'); buttons.classList.add('guanxing'); buttons._link=i; if(list[i][1]){ if(get.itemtype(list[i][1])=='cards'){ var cardsb=ui.create.buttons(list[i][1],'card',buttons); if(list[i][2]&&typeof list[i][2]=='string'){ for(var ij of cardsb) ij.node.gaintag.innerHTML=get.translation(list[i][2]); } } else if(list[i][1].length==2){ ui.create.buttons(list[i][1][0],list[i][1][1],buttons); } } if(list[i][2]&&typeof list[i][2]=='function') buttons.textPrompt=list[i][2]; } var tex=event.dialog.add('
        点击两张牌以交换位置;点击一张牌并点击其他区域以移动卡牌
        '); tex.classList.add('choosetomove'); event.dialog.open(); updateButtons(); event.custom.replace.button=function(button){ var node=button.parentNode; if(!buttonss.contains(node)) return; if(!ui.selected.guanxing_button){ ui.selected.guanxing_button=button; button.classList.add('glow2'); return; } if(ui.selected.guanxing_button==button){ button.classList.remove('glow2'); delete ui.selected.guanxing_button; return; } if(!filterMove(button,ui.selected.guanxing_button,event.moved)) return; var par1=ui.selected.guanxing_button.parentNode,ind1=ui.selected.guanxing_button.nextSibling,par2=button.parentNode,ind2=button.nextSibling; ui.selected.guanxing_button.classList.remove('glow2'); par1.insertBefore(button,ind1); par2.insertBefore(ui.selected.guanxing_button,ind2); delete ui.selected.guanxing_button; updateButtons(); } event.custom.replace.confirm=function(bool){ if(bool) event._result={ bool:true, moved:event.moved, }; else event._result={bool:false}; event.dialog.close(); if(ui.confirm) ui.confirm.close(); game.resume(); _status.imchoosing=false; setTimeout(function(){ ui.arena.classList.remove('choose-to-move'); },500); }; game.pause(); game.countChoose(); event.choosing=true; } else if(event.isOnline()){ event.send(); } else{ event.result='ai'; } "step 1" if(event.time) game.broadcastAll(function(time){ lib.configOL.choose_timeout=time; },event.time); var result=event.result||result; if((!result||result=='ai'||(event.forced&&!result.bool))&&event.processAI){ var moved=event.processAI(event.list); if(moved) result={ bool:true, moved:moved, } else result={bool:false}; } event.result=result; }, showCharacter:function(){ 'step 0' event.trigger('showCharacterEnd'); 'step 1' event.trigger('showCharacterAfter'); if(get.mode()=='identity'&&player.isZhu) event.trigger('zhuUpdate'); }, removeCharacter:function(){ player.$removeCharacter(event.num); }, chooseUseTarget:function(){ 'step 0' if(get.is.object(card)&&!event.viewAs) card.isCard=true; if(cards&&get.itemtype(card)!='card'){ card=get.copy(card); card.cards=cards.slice(0); event.card=card; } if(!lib.filter.cardEnabled(card,player)||(event.addCount!==false&&!lib.filter.cardUsable(card,player))){ event.result={bool:false}; event.finish(); return; } var info=get.info(card); var range; if(!info.notarget){ var select=get.copy(info.selectTarget); range=get.select(select); if(event.selectTarget) range=get.select(event.selectTarget); game.checkMod(card,player,range,'selectTarget',player); } if(info.notarget||range[1]<=-1){ if(!info.notarget&&range[1]<=-1){ for(var i=0;i0; }; } } else{ if(event.filterTarget){ var targets=game.filterPlayer(function(current){ return event.filterTarget(card,player,current); }); if(targets.length6){ var cards=_status.renku.splice(0,_status.renku.length-6); game.log(cards,'从仁库进入了弃牌堆'); game.cardsDiscard(cards).set('outRange',true).fromRenku=true; } game.updateRenku(); } }, cardsGotoPile:function(){ if(event.washCard){ event.trigger('washCard') for(var i=0;igame.players.length*num&&game.showIdentity){ if(!_status.video) player.popup('显示身份'); _status.identityShown=true; game.showIdentity(false); } } player.ai.tempIgnore=[]; if(ui.land&&ui.land.player==player){ game.addVideo('destroyLand'); ui.land.destroy(); } 'step 1' event.trigger('phaseBeginStart'); }, toggleSubPlayer:function(){ 'step 0' var list=event.list||player.storage.subplayer.skills.slice(0); list.remove(player.storage.subplayer.name2); event.list=list; if(!event.directresult){ if(list.length>1){ var dialog=ui.create.dialog('更换一个随从','hidden'); dialog.add([list,'character']); player.chooseButton(dialog,true); } else if(list.length==1){ event.directresult=list[0]; } else{ event.finish(); } } else{ if(!list.contains(event.directresult)){ event.finish(); } } 'step 1' if(!event.directresult){ if(result&&result.bool&&result.links[0]){ event.directresult=result.links[0]; } else{ event.finish(); return; } } if(player.storage.subplayer){ var current=player.storage.subplayer.name2; if(event.directresult==current){ event.finish(); return; } player.storage[current].hp=player.hp; player.storage[current].maxHp=player.maxHp; player.storage[current].hs=player.getCards('h'); player.storage[current].es=player.getCards('e'); player.lose(player.getCards('he'),ui.special)._triggered=null; var cfg=player.storage[event.directresult]; player.storage.subplayer.name2=event.directresult; player.reinit(current,event.directresult,[ cfg.hp, cfg.maxHp ]); if(cfg.hs.length) player.directgain(cfg.hs); if(cfg.es.length) player.directequip(cfg.es); } }, exitSubPlayer:function(){ 'step 0' if(player.storage.subplayer){ var current=player.storage.subplayer.name2; if(event.remove){ player.lose(player.getCards('he'),ui.discardPile)._triggered=null; } else{ player.storage[current].hp=player.hp; player.storage[current].maxHp=player.maxHp; player.storage[current].hs=player.getCards('h'); player.storage[current].es=player.getCards('e'); player.lose(player.getCards('he'),ui.special)._triggered=null; } player.reinit(current,player.storage.subplayer.name,[ player.storage.subplayer.hp, player.storage.subplayer.maxHp ]); player.update(); if(event.remove){ if(player.storage[current].onremove){ player.storage[current].onremove(player); } delete player.storage[current]; player.storage.subplayer.skills.remove(current); game.log(player,'牺牲了随从','#g'+current); } else{ game.log(player,'收回了随从','#g'+current); } player.addSkill(player.storage.subplayer.skills); } 'step 1' if(player.storage.subplayer){ player.directgain(player.storage.subplayer.hs); player.directequip(player.storage.subplayer.es); } player.removeSkill('subplayer'); 'step 2' if(event.remove){ event.trigger('subPlayerDie'); } }, callSubPlayer:function(){ 'step 0' var list=player.getSubPlayers(event.tag); event.list=list; if(!event.directresult){ if(list.length>1){ var dialog=ui.create.dialog('调遣一个随从','hidden'); dialog.add([list,'character']); player.chooseButton(dialog,true); } else if(list.length==1){ event.directresult=list[0]; } else{ event.finish(); } } else{ if(!list.contains(event.directresult)){ event.finish(); } } 'step 1' if(!event.directresult){ if(result&&result.bool&&result.links[0]){ event.directresult=result.links[0]; } else{ event.finish(); return; } } if(event.directresult){ var cfg=player.storage[event.directresult]; var source=cfg.source||player.name; var name=event.directresult; game.log(player,'调遣了随从','#g'+name); player.storage.subplayer={ name:source, name2:event.directresult, hp:player.hp, maxHp:player.maxHp, skills:event.list.slice(0), hs:player.getCards('h'), es:player.getCards('e'), intro2:cfg.intro2 } player.removeSkill(event.list); player.reinit(source,name,[cfg.hp,cfg.maxHp]); player.addSkill('subplayer'); player.lose(player.getCards('he'),ui.special)._triggered=null; if(cfg.hs.length) player.directgain(cfg.hs); if(cfg.es.length) player.directequip(cfg.es); } 'step 2' game.delay(); }, addExtraTarget:function(){ "step 0" event.num=0; "step 1" var target=targets[num],info=get.info(card); if(target==event.target&&event.addedTarget){ event.addedTargets[num]=event.addedTarget; event._result={bool:false}; } else if(game.hasPlayer(function(current){ return info.filterAddedTarget(card,player,current,target) })){ var next=player.chooseTarget(get.translation(event.card)+':选择'+get.translation(targets[num])+'对应的指向目标',function(card,player,target){ var card=get.card(),info=get.info(card); return info.filterAddedTarget(card,player,target,_status.event.preTarget) },true); next.set('_get_card',card); next.set('preTarget',targets[num]); } else{ event.addedTargets[num]=false; event._result={bool:false}; } "step 2" if(result.bool){ event.addedTargets[num]=result.targets[0]; player.line2([targets[num],result.targets[0]]); } event.num++; if(event.numpriority){ event.doing.list.splice(i--,1); event.num--; } } event.choice=[]; if(event.num
      • '+trans+'栏:'+num+'个
        ' } } if(str.length) return str.slice(0,str.length-4); return '当前没有扩展装备栏'; }, }, }, charge:{ markimage:'image/card/charge.png', intro:{ content:'当前蓄力点数:#', }, }, cooperation:{ charlotte:true, trigger:{ global:['phaseAfter','dieAfter'], }, forced:true, lastDo:true, filter:function(event,player){ if(event.name=='die'&&event.player.isAlive()) return false; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.target==event.player) return true; } return false; }, content:function(){ for(var i=0;i(info.damage&&info.damage>3), content:function(){ var source=trigger.source; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='damage'&&(source==player||source==info.target)){ if(!info.damage) info.damage=0; info.damage+=trigger.num; } } player.markSkill('cooperation_damage'); }, marktext:'仇', intro:{ name:'协力 - 同仇', markcount:function(storage,player){ return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){ return info.damage||0; })); }, content:function(storage,player){ var str='',storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='damage'){ str+='
      • 协力角色:'+get.translation(info.target); str+='
      • 协力原因:'+get.translation(info.reason); str+='
      • 协力进度:' var num=(info.damage||0); str+=num; str+='/4'; str+=(num>3?' (已完成)':' (未完成)'); str+='
          '; } } return str.slice(4,str.length-6); }, }, }, draw:{ mark:true, trigger:{global:'gainAfter'}, forced:true, charlotte:true, popup:false, firstDo:true, filter:function(event,player){ if(event.getParent().name!='draw') return false; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='draw'&&(event.player==player||event.player==info.target)) return true; } return false; }, checkx:(info)=>(info.draw&&info.draw>7), content:function(){ var source=trigger.player; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='draw'&&(source==player||source==info.target)){ if(!info.draw) info.draw=0; info.draw+=trigger.cards.length; } } player.markSkill('cooperation_draw'); }, marktext:'进', intro:{ name:'协力 - 并进', markcount:function(storage,player){ return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){ return info.draw||0; })); }, content:function(storage,player){ var str='',storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='draw'){ str+='
      • 协力角色:'+get.translation(info.target); str+='
      • 协力原因:'+get.translation(info.reason); str+='
      • 协力进度:' var num=(info.draw||0); str+=num; str+='/8'; str+=(num>7?' (已完成)':' (未完成)'); str+='
          '; } } return str.slice(4,str.length-6); }, }, }, discard:{ mark:true, trigger:{global:'loseAfter'}, forced:true, charlotte:true, popup:false, firstDo:true, filter:function(event,player){ if(event.type!='discard') return false; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='discard'&&(event.player==player||event.player==info.target)) return true; } return false; }, checkx:(info)=>(info.discard&&info.discard.length>3), content:function(){ var source=trigger.player; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='discard'&&(source==player||source==info.target)){ if(!info.discard) info.discard=[]; for(var i of trigger.cards2){ var suit=get.suit(i,player); if(lib.suit.contains(suit)) info.discard.add(suit); } } } player.markSkill('cooperation_discard'); }, marktext:'财', intro:{ name:'协力 - 疏财', markcount:function(storage,player){ return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){ return info.discard?info.discard.length:0; })); }, content:function(storage,player){ var str='',storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='discard'){ str+='
      • 协力角色:'+get.translation(info.target); str+='
      • 协力原因:'+get.translation(info.reason); str+='
      • 进度:'; var suits=info.discard||[]; var suits2=[['spade','♠','♤'],['heart','♥','♡'],['club','♣','♧'],['diamond','♦','♢']]; for(var i of suits2){ str+=(suits.contains(i[0])?i[1]:i[2]); } str+=(suits.length>3?' (已完成)':' (未完成)'); str+='
          '; } } return str.slice(4,str.length-6); }, }, }, use:{ mark:true, trigger:{global:'useCard1'}, forced:true, charlotte:true, popup:false, firstDo:true, filter:function(event,player){ var suit=get.suit(event.card); if(!lib.suit.contains(suit)) return false; var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='use' &&(event.player==player||event.player==info.target)&& (!info.used||!info.used.contains(suit))) return true; } return false; }, checkx:(info)=>(info.used&&info.used.length>3), content:function(){ var source=trigger.player,suit=get.suit(trigger.card); var storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='use'&&(source==player||source==info.target)){ if(!info.used) info.used=[]; info.used.add(suit); } } player.markSkill('cooperation_use'); }, marktext:'戮', intro:{ name:'协力 - 戮力', markcount:function(storage,player){ return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){ return info.used?info.used.length:0; })); }, content:function(storage,player){ var str='',storage=player.getStorage('cooperation'); for(var info of storage){ if(info.type=='use'){ str+='
      • 协力角色:'+get.translation(info.target); str+='
      • 协力原因:'+get.translation(info.reason); str+='
      • 进度:'; var suits=info.used||[]; var suits2=[['spade','♠','♤'],['heart','♥','♡'],['club','♣','♧'],['diamond','♦','♢']]; for(var i of suits2){ str+=(suits.contains(i[0])?i[1]:i[2]); } str+=(suits.length>3?' (已完成)':' (未完成)'); str+='
          '; } } return str.slice(4,str.length-6); }, }, }, }, }, zhengsu:{ trigger:{player:'phaseDiscardEnd'}, forced:true, charlotte:true, filter:function(event,player){ return (player.storage.zhengsu_leijin||player.storage.zhengsu_bianzhen||player.storage.zhengsu_mingzhi); }, content:function(){ player.chooseDrawRecover(2,'整肃奖励:摸两张牌或回复1点体力'); }, subSkill:{ leijin:{ mod:{ aiOrder:function(player,card,num){ if(typeof card.number!='number') return; var history=player.getHistory('useCard',evt=>evt.isPhaseUsing()); if(history.length==0) return num+10*(14-card.number); var num=get.number(history[0].card); if(!num) return; for(var i=1;inum) return num+10*(14-card.number); }, }, mark:true, trigger:{player:'useCard1'}, lastDo:true, charlotte:true, forced:true, popup:false, onremove:true, filter:function(event,player){ return player.isPhaseUsing()&&player.storage.zhengsu_leijin!==false; }, content:function(){ var list=player.getHistory('useCard',function(evt){ return evt.isPhaseUsing(player); }); var goon=true; for(var i=0;i0){ var num2=get.number(list[i-1].card); if(typeof num2!='number'||num2>=num){ goon=false; break; } } } if(!goon){ game.broadcastAll(function(player){ player.storage.zhengsu_leijin=false; if(player.marks.zhengsu_leijin) player.marks.zhengsu_leijin.firstChild.innerHTML='╳'; delete player.storage.zhengsu_leijin_markcount; },player); } else{ if(list.length>2){ game.broadcastAll(function(player,num){ if(player.marks.zhengsu_leijin) player.marks.zhengsu_leijin.firstChild.innerHTML='○'; player.storage.zhengsu_leijin=true; player.storage.zhengsu_leijin_markcount=num; },player,num); } else game.broadcastAll(function(player,num){ player.storage.zhengsu_leijin_markcount=num; },player,num); } player.markSkill('zhengsu_leijin'); }, intro:{ content:'
      • 条件:回合内所有于出牌阶段使用的牌点数递增且不少于三张。', }, }, bianzhen:{ mark:true, trigger:{player:'useCard1'}, firstDo:true, charlotte:true, forced:true, popup:false, onremove:true, filter:function(event,player){ return player.isPhaseUsing()&&player.storage.zhengsu_bianzhen!==false; }, content:function(){ var list=player.getHistory('useCard',function(evt){ return evt.isPhaseUsing(); }); var goon=true,suit=get.suit(list[0].card,false); if(suit=='none'){ goon=false; } else{ for(var i=1;i1){ game.broadcastAll(function(player){ if(player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML='○'; player.storage.zhengsu_bianzhen=true; },player); } else game.broadcastAll(function(player,suit){ if(player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML=get.translation(suit); },player,suit); } player.markSkill('zhengsu_bianzhen'); }, intro:{ content:'
      • 条件:回合内所有于出牌阶段使用的牌花色相同且不少于两张。', }, ai:{ effect:{ player_use:function(card,player,target){ if(typeof card!='object'||!player.isPhaseUsing()) return; var suitx=get.suit(card); var history=player.getHistory('useCard'); if(!history.length){ var val=0; if(player.hasCard(function(cardx){ return get.suit(cardx)==suitx&&card!=cardx&&(!card.cards||!card.cards.contains(cardx))&&player.hasValueTarget(cardx); },'hs')) val=[2,0.1]; if(val) return val; return; } var num=0; var suit=false; for(var i=0;i1||num<=1&&player.hasCard(function(cardx){ return get.suit(cardx)==suit&&player.hasValueTarget(cardx); },'hs'))) return 'zeroplayertarget'; }, }, }, }, mingzhi:{ mark:true, trigger:{player:'loseAfter'}, firstDo:true, charlotte:true, forced:true, popup:false, onremove:true, filter:function(event,player){ if(player.storage.zhengsu_mingzhi===false||event.type!='discard') return false; var evt=event.getParent('phaseDiscard'); return evt&&evt.player==player; }, content:function(){ var goon=true,list=[]; player.getHistory('lose',function(event){ if(!goon||event.type!='discard') return false; var evt=event.getParent('phaseDiscard'); if(evt&&evt.player==player){ for(var i of event.cards2){ var suit=get.suit(i,player); if(list.contains(suit)){ goon=false; break; } else list.push(suit); } } }); if(!goon){ game.broadcastAll(function(player){ player.storage.zhengsu_mingzhi=false; if(player.marks.zhengsu_mingzhi) player.marks.zhengsu_mingzhi.firstChild.innerHTML='╳'; delete player.storage.zhengsu_mingzhi_list; },player); } else{ if(list.length>1){ game.broadcastAll(function(player,list){ if(player.marks.zhengsu_mingzhi) player.marks.zhengsu_mingzhi.firstChild.innerHTML='○'; player.storage.zhengsu_mingzhi=true; player.storage.zhengsu_mingzhi_list=list; player.storage.zhengsu_mingzhi_markcount=list.length; },player,list); } else game.broadcastAll(function(player,list){ player.storage.zhengsu_mingzhi_list=list; player.storage.zhengsu_mingzhi_markcount=list.length; },player,list); } player.markSkill('zhengsu_mingzhi'); }, intro:{ content:'
      • 条件:回合内所有于弃牌阶段弃置的牌花色均不相同且不少于两张。', }, }, }, }, renku:{ intro:{ markcount:function(){ return _status.renku.length; }, mark:function(dialog,content,player){ if(!_status.renku.length) return '仁库中没有牌'; else dialog.addAuto(_status.renku); }, content:function(){ if(!_status.renku.length) return '仁库中没有牌'; return get.translation(_status.renku); }, }, }, _showHiddenCharacter:{ trigger:{player:['changeHp','phaseBeginStart','loseMaxHpBegin','gainMaxHpBegin']}, firstDo:true, forced:true, popup:false, priority:25, filter:function(event,player,name){ return player.isUnseen(2)&&get.mode()!='guozhan'; }, content:function(){ player.showCharacter(2); player.removeSkill('g_hidden_ai'); }, }, _kamisha:{ trigger:{source:'damageBegin2'}, //forced:true, popup:false, prompt:function(event,player){ return '是否防止即将对'+get.translation(event.player)+'造成的伤害,改为令其减少'+get.cnNumber(event.num)+'点体力上限?'; }, filter:function(event,player){ return event.hasNature('kami')&&event.num>0; }, ruleSkill:true, check:function(event,player){ var att=get.attitude(player,event.player); if(event.player.hp==event.player.maxHp) return att<0; if(event.player.hp==event.player.maxHp-1&& (event.player.maxHp<=3||event.player.hasSkillTag('maixie'))) return att<0; return att>0; }, content:function(){ trigger.cancel(); trigger.player.loseMaxHp(trigger.num).source=player; }, }, aozhan:{ charlotte:true, mod:{ targetEnabled:function(card){ if(card.name=='tao'&&(card.isCard&&card.cardid||get.itemtype(card)=='card')) return false; }, cardSavable:function(card){ if(card.name=='tao'&&(card.isCard&&card.cardid||get.itemtype(card)=='card')) return false; }, }, group:["aozhan_sha","aozhan_shan"], subSkill:{ sha:{ enable:["chooseToUse","chooseToRespond"], filterCard:{ name:"tao", }, viewAs:{ name:"sha", isCard:true, }, viewAsFilter:function (player){ if(!player.countCards('hs','tao')) return false; }, position:'hs', prompt:"将一张桃当杀使用或打出", check:function (){return 1}, ai:{ respondSha:true, skillTagFilter:function(player){ if(!player.countCards('hs','tao')) return false; }, order:function(){ return get.order({name:'sha'})-0.1; }, }, sub:true, }, shan:{ enable:["chooseToRespond","chooseToUse"], filterCard:{ name:"tao", }, viewAs:{ name:"shan", isCard:true, }, prompt:"将一张桃当闪打出", check:function (){return 1}, viewAsFilter:function (player){ if(!player.countCards('hs','tao')) return false; }, position:'hs', ai:{ respondShan:true, skillTagFilter:function(player){ if(!player.countCards('hs','tao')) return false; }, }, sub:true, }, }, }, global:[], globalmap:{}, storage:{}, undist:{}, others:{}, zhu:{}, zhuSkill:{}, land_used:{}, unequip:{ai:{unequip:true}}, subplayer:{ trigger:{player:'dieBefore'}, forced:true, priority:-9, onremove:true, mark:'character', intro:{ content:function(storage,player){ if(typeof storage.intro2=='string') return storage.intro2; if(typeof storage.intro2=='function') return storage.intro2(storage,player); return '死亡前切换回主武将' }, name:function(storage){ return get.rawName(storage.name); } }, content:function(){ trigger.cancel(); var evt=trigger.getParent('damage'); if(evt.player==player){ evt.untrigger(false,player); } player.exitSubPlayer(true); }, ai:{ nosave:true } }, autoswap:{ firstDo:true, trigger:{player:['playercontrol','chooseToUseBegin','chooseToRespondBegin','chooseToDiscardBegin','chooseToCompareBegin', 'chooseButtonBegin','chooseCardBegin','chooseTargetBegin','chooseCardTargetBegin','chooseControlBegin', 'chooseBoolBegin','choosePlayerCardBegin','discardPlayerCardBegin','gainPlayerCardBegin','chooseToMoveBegin','chooseToPlayBeatmapBegin']}, forced:true, priority:100, forceDie:true, popup:false, filter:function(event,player){ if(event.autochoose&&event.autochoose()) return false; if(lib.filter.wuxieSwap(event)) return false; if(_status.auto||!player.isUnderControl()) return false; return true; }, content:function(){ game.swapPlayerAuto(player); }, }, dualside:{ charlotte:true, subSkill:{ turn:{ trigger:{player:['turnOverAfter','dieBefore']}, silent:true, filter:function(event,player){ if(player.storage.dualside_over) return false; return Array.isArray(player.storage.dualside); }, content:function(){ var cfg=player.storage.dualside; var bool=player.isTurnedOver(); if(trigger.name=='die'){ bool=!bool; } if(bool){ cfg[1]=player.hp; cfg[2]=player.maxHp; player.reinit(cfg[0],cfg[3],[cfg[4],cfg[5]]); player.unmarkSkill('dualside'); player.markSkillCharacter('dualside',{name:cfg[0]},'正面','当前体力:'+cfg[1]+'/'+cfg[2]); } else{ cfg[4]=player.hp; cfg[5]=player.maxHp; player.reinit(cfg[3],cfg[0],[cfg[1],cfg[2]]); player.unmarkSkill('dualside'); player.markSkillCharacter('dualside',{name:cfg[3]},'背面','当前体力:'+cfg[4]+'/'+cfg[5]); } if(trigger.name=='die'){ trigger.cancel(); delete player.storage.dualside; player.storage.dualside_over=true; player.unmarkSkill('dualside'); } } }, init:{ trigger:{global:'gameStart',player:'enterGame'}, silent:true, content:function(){ var list=[player.name,player.name1,player.name2]; for(var i=0;i=player.maxHp; }, content:function(){ trigger.cancel(); }, }, /** * @deprecated */ /*_turnover:{ trigger:{player:'phaseBefore'}, forced:true, forceOut:true, priority:100, popup:false, firstDo:true, content:function(){ if(player.isTurnedOver()&&!trigger._noTurnOver){ trigger.cancel(); player.turnOver(); player.phaseSkipped=true; } else{ player.phaseSkipped=false; } var isRound=false; if(!trigger.skill){ isRound=_status.roundSkipped; if(_status.isRoundFilter){ isRound=_status.isRoundFilter(trigger,player); } else if(_status.seatNumSettled){ var seatNum=player.getSeatNum(); if(seatNum!=0){ if(typeof _status.lastSeatNum!='number'||seatNum<_status.lastSeatNum) isRound=true; _status.lastSeatNum=seatNum; } } else if(player==_status.roundStart) isRound=true; if(isRound){ delete _status.roundSkipped; game.roundNumber++; trigger._roundStart=true; game.updateRoundNumber(); for(var i=0;i0){ game.players[i].outCount--; if(game.players[i].outCount==0&&!game.players[i].outSkills){ game.players[i].in(); } } } event.trigger('roundStart'); } } _status.globalHistory.push({ cardMove:[], custom:[], useCard:[], changeHp:[], everything:[], }); var players=game.players.slice(0).concat(game.dead); for(var i=0;iplayer.hasCard(card=>lib.skill._recasting.filterCard(card,player),lib.skill._recasting.position), position:'he', filterCard:(card,player)=>player.canRecast(card,null,true), discard:false, lose:false, delay:false, content:()=>{ player.recast(cards,null,(player,cards)=>{ var numberOfCardsToDraw=cards.length; cards.forEach(value=>{ if(lib.config.mode=='stone'&&_status.mode=='deck'&&!player.isMin()&&get.type(value).startsWith('stone')){ var stonecard=get.stonecard(1,player.career); if(stonecard.length){ numberOfCardsToDraw-=stonecard.length; player.gain(game.createCard(stonecard.randomGet()),'draw'); } else player.draw({ drawDeck:1 }).log=false; } else if(get.subtype(value)=='spell_gold'){ var libCard=get.libCard(info=>info.subtype=='spell_silver'); if(!libCard.length) return; numberOfCardsToDraw--; player.gain(game.createCard(libCard.randomGet()),'draw'); } else if(get.subtype(value)=='spell_silver'){ var libCard=get.libCard(info=>info.subtype=='spell_bronze'); if(!libCard.length) return; numberOfCardsToDraw--; player.gain(game.createCard(libCard.randomGet()),'draw'); } }); if(numberOfCardsToDraw) player.draw(numberOfCardsToDraw).log=false; }); }, ai:{ basic:{ order:6 }, result:{ player:1 } } }, _lianhuan:{ trigger:{player:'damageAfter'}, filter:function(event,player){ return event.lianhuanable==true; }, forced:true, popup:false, logv:false, forceDie:true, //priority:-5, content:function(){ "step 0" event.logvid=trigger.getLogv(); "step 1" event.targets=game.filterPlayer(function(current){ return current!=event.player&¤t.isLinked(); }); lib.tempSortSeat=_status.currentPhase||player; event.targets.sort(lib.sort.seat); delete lib.tempSortSeat; event._args=[trigger.num,trigger.nature,trigger.cards,trigger.card]; if(trigger.source) event._args.push(trigger.source); else event._args.push("nosource"); "step 2" if(event.targets.length){ var target=event.targets.shift(); if(target.isLinked()) target.damage.apply(target,event._args.slice(0)); event.redo(); } }, }, _lianhuan4:{ trigger:{player:'changeHp'}, priority:-10, forced:true, popup:false, forceDie:true, filter:function(event,player){ var evt=event.getParent(); return evt&&evt.name=='damage'&&evt.hasNature('linked')&&player.isLinked(); }, content:function(){ player.link(); if(trigger.getParent().notLink()) trigger.getParent().lianhuanable=true; } }, /** * @deprecated */ _chongzhu:{ get filter(){ return lib.skill._recasting.filter; }, set filter(filter){ lib.skill._recasting.filter=filter; }, get filterCard(){ return lib.skill._recasting.filterCard; }, set filterCard(filterCard){ lib.skill._recasting.filterCard=filterCard; }, get content(){ return lib.skill._recasting.content; }, set content(content){ lib.skill._recasting.content=content; }, get ai(){ return lib.skill._recasting.ai; }, set ai(ai){ lib.skill._recasting.ai=ai; } } }, character:{}, perfectPair:{}, cardPile:{}, message:{ server:{ init:function(version,config,banned_info){ if(lib.node.banned.contains(banned_info)){ this.send('denied','banned'); } else if(config.id&&lib.playerOL&&lib.playerOL[config.id]){ var player=lib.playerOL[config.id]; player.setNickname(); player.ws=this; player.isAuto=false; this.id=config.id; game.broadcast(function(player){ player.setNickname(); },player); this.send('reinit',lib.configOL,get.arenaState(),game.getState?game.getState():{},game.ip,null,_status.onreconnect,_status.cardtag,_status.postReconnect); } else if(version!=lib.versionOL){ this.send('denied','version'); lib.node.clients.remove(this); this.closed=true; } else if(!_status.waitingForPlayer){ if(game.phaseNumber&&lib.configOL.observe){ lib.node.observing.push(this); this.send('reinit',lib.configOL,get.arenaState(),game.getState?game.getState():{},game.ip,game.players[0].playerid,null,_status.cardtag); if(!ui.removeObserve){ ui.removeObserve=ui.create.system('移除旁观',function(){ lib.configOL.observe=false; if(game.onlineroom){ game.send('server','config',lib.configOL); } while(lib.node.observing.length){ lib.node.observing.shift().ws.close(); } this.remove(); delete ui.removeObserve; },true,true); } } else{ this.send('denied','gaming'); lib.node.clients.remove(this); this.closed=true; } } else if(lib.node.clients.length-(window.isNonameServer?1:0)>=parseInt(lib.configOL.number)){ this.send('denied','number'); lib.node.clients.remove(this); this.closed=true; } else{ if(config){ this.avatar=config.avatar; this.nickname=config.nickname; } for(var i=0;ilib.init.connection(lib.wsOL[id]=new lib.element.NodeWS(id)), onmessage:function(id,message){ if(lib.wsOL[id]){ lib.wsOL[id].onmessage(message); } }, onclose:function(id){ if(lib.wsOL[id]){ lib.wsOL[id].onclose(); } }, selfclose:function(){ if(game.online||game.onlineroom){ if((game.servermode||game.onlinehall)&&_status.over){ // later } else{ game.saveConfig('tmp_user_roomId'); } } game.ws.close(); }, reloadroom:function(forced){ if(window.isNonameServer&&(forced||!_status.protectingroom)){ game.reload(); } }, createroom:function(index,config,mode){ game.online=false; game.onlineroom=true; game.roomId=index; lib.node={}; if(config&&mode&&window.isNonameServer){ if(mode=='auto'){ mode=lib.configOL.mode; } game.switchMode(mode,config); } else{ game.switchMode(lib.configOL.mode); } ui.create.connecting(true); }, enterroomfailed:function(){ alert('请稍后再试'); _status.enteringroom=false; ui.create.connecting(true); }, roomlist:function(list,events,clients,wsid){ game.send('server','key',[game.onlineKey,lib.version]); game.online=true; game.onlinehall=true; lib.config.recentIP.remove(_status.ip); lib.config.recentIP.unshift(_status.ip); lib.config.recentIP.splice(5); if(!lib.config.reconnect_info||lib.config.reconnect_info[0]!=_status.ip){ game.saveConfig('reconnect_info',[_status.ip,null]); } game.saveConfig('recentIP',lib.config.recentIP); _status.connectMode=true; game.clearArena(); game.clearConnect(); ui.pause.hide(); ui.auto.hide(); clearTimeout(_status.createNodeTimeout); game.send('server','changeAvatar',get.connectNickname(),lib.config.connect_avatar); var proceed=function(){ game.ip=get.trimip(_status.ip); ui.create.connectRooms(list); if(events){ ui.connectEvents=ui.create.div('.forceopaque.menubutton.large.connectevents.pointerdiv','约战',ui.window,ui.click.connectEvents); ui.connectEventsCount=ui.create.div('.forceopaque.menubutton.icon.connectevents.highlight.hidden','',ui.window); ui.connectClients=ui.create.div('.forceopaque.menubutton.large.connectevents.pointerdiv.left','在线',ui.window,ui.click.connectClients); ui.connectClientsCount=ui.create.div('.forceopaque.menubutton.icon.connectevents.highlight.left','1',ui.window); ui.createRoomButton=ui.create.div('.forceopaque.menubutton.large.connectevents.pointerdiv.left2','创建房间',ui.window,function(){ if(!_status.creatingroom){ _status.creatingroom=true; ui.click.connectMenu(); } }); if(events.length){ ui.connectEventsCount.innerHTML=events.filter(function(evt){ return evt.creator==game.onlineKey||!get.is.banWords(evt.content) }).length; ui.connectEventsCount.show(); } } game.wsid=wsid; lib.message.client.updaterooms(list,clients); lib.message.client.updateevents(events); ui.exitroom=ui.create.system('退出房间',function(){ game.saveConfig('tmp_owner_roomId'); game.saveConfig('tmp_user_roomId'); if(ui.rooms){ game.saveConfig('reconnect_info'); } else{ if(lib.config.reconnect_info){ lib.config.reconnect_info.length=1; game.saveConfig('reconnect_info',lib.config.reconnect_info); } } game.reload(); },true); var findRoom=function(id){ for(var room of ui.rooms){ if(room.key==id) return room; } return false; }; if(typeof lib.config.tmp_owner_roomId=='string'){ if(typeof game.roomId!='string'&&!findRoom(lib.config.tmp_owner_roomId)){ lib.configOL.mode=lib.config.connect_mode; game.roomId=lib.config.tmp_owner_roomId; } game.saveConfig('tmp_owner_roomId'); } if(typeof lib.config.tmp_user_roomId=='string'){ if(typeof game.roomId!='string'){ if(findRoom(lib.config.tmp_user_roomId)){ game.roomId=lib.config.tmp_user_roomId; } else{ ui.create.connecting(); (function(){ var n=10; var id=lib.config.tmp_user_roomId; var interval=setInterval(function(){ if(n>0){ n--; if(findRoom(id)){ clearInterval(interval); game.send('server','enter',id,get.connectNickname(),lib.config.connect_avatar); } } else{ ui.create.connecting(true); clearInterval(interval); } },500); }()); } } game.saveConfig('tmp_user_roomId'); } if(window.isNonameServer){ var cfg='pagecfg'+window.isNonameServer; if(lib.config[cfg]){ lib.configOL=lib.config[cfg][0]; game.send('server','server',lib.config[cfg].slice(1)); game.saveConfig(cfg); _status.protectingroom=true; setTimeout(function(){ _status.protectingroom=false; if(!lib.node||!lib.node.clients||!lib.node.clients.length){ game.reload(); } },15000); } else{ game.send('server','server'); } } else if(typeof game.roomId=='string'){ var room=findRoom(game.roomId); if(game.roomIdServer&&room&&(room.serving||!room.version)){ console.log(); if(lib.config.reconnect_info){ lib.config.reconnect_info[2]=null; game.saveConfig('reconnect_info',lib.config.reconnect_info); } } else{ ui.create.connecting(); game.send('server',(game.roomId==game.onlineKey)?'create':'enter',game.roomId,get.connectNickname(),lib.config.connect_avatar); } } lib.init.onfree(); } if(_status.event.parent){ game.forceOver('noover',proceed); } else{ proceed(); } }, updaterooms:function(list,clients){ if(ui.rooms){ var map={},map2={}; for(var i of ui.rooms) map2[i.key]=true; for(var i of list){ if(!i) continue; map[i[4]]=i; } ui.window.classList.add('more_room'); for(var i=0;i空房间'); player.roomindex=i; player.initRoom=lib.element.Player.prototype.initRoom; player.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.connectroom); player.initRoom(i); ui.rooms.push(player); } } } lib.message.client.updateclients(clients,true); }, updateclients:function(clients,bool){ if(clients&&ui.connectClients){ ui.connectClients.info=clients; ui.connectClientsCount.innerHTML=clients.length; } if(_status.connectClientsCallback){ _status.connectClientsCallback(); } }, updateevents:function(events){ if(events&&ui.connectEvents){ ui.connectEvents.info=events; var num=events.filter(function(evt){ return typeof evt.creator=='string'&&(evt.creator==game.onlineKey||!get.is.banWords(evt.content)) }).length; if(num){ ui.connectEventsCount.innerHTML=num; ui.connectEventsCount.show(); } else{ ui.connectEventsCount.hide(); } if(_status.connectEventsCallback){ _status.connectEventsCallback(); } } }, eventsdenied:function(reason){ var str='创建约战失败'; if(reason=='total'){ str+=',约战总数不能超过20'; } else if(reason=='time'){ str+=',时间已过'; } else if(reason=='ban'){ str+=',请注意文明发言'; } alert(str); }, init:function(id,config,ip,servermode,roomId){ game.online=true; game.onlineID=id; game.ip=ip; game.servermode=servermode; game.roomId=roomId; if(game.servermode){ game.saveConfig('reconnect_info',[_status.ip,id,game.roomId]); } else{ game.saveConfig('reconnect_info',[_status.ip,id]); game.saveConfig('tmp_user_roomId',roomId); } lib.config.recentIP.remove(_status.ip); lib.config.recentIP.unshift(_status.ip); lib.config.recentIP.splice(5); game.saveConfig('recentIP',lib.config.recentIP); _status.connectMode=true; lib.configOL=config; lib.playerOL={}; lib.cardOL={}; game.clearArena(); game.finishCards(); ui.create.roomInfo(); ui.create.chat(); if(game.servermode){ ui.create.connectPlayers(get.modetrans(config,true)); } else{ ui.create.connectPlayers(ip); } ui.pause.hide(); ui.auto.hide(); game.clearConnect(); clearTimeout(_status.createNodeTimeout); var proceed=function(){ game.loadModeAsync(config.mode,function(mode){ for(var i in mode.ai){ if(typeof mode.ai[i]=='object'){ if(ai[i]==undefined) ai[i]={}; for(var j in mode.ai[i]){ ai[i][j]=mode.ai[i][j]; } } else{ ai[i]=mode.ai[i]; } } for(var i in mode.get){ if(typeof mode.get[i]=='object'){ if(get[i]==undefined) get[i]={}; for(var j in mode.get[i]){ get[i][j]=mode.get[i][j]; } } else{ get[i]=mode.get[i]; } } for(var i in mode.translate){ lib.translate[i]=mode.translate[i]; } if(mode.game){ game.getIdentityList=mode.game.getIdentityList; game.updateState=mode.game.updateState; game.getRoomInfo=mode.game.getRoomInfo; } if(mode.element&&mode.element.player){ Object.defineProperties(lib.element.Player.prototype,Object.getOwnPropertyDescriptors(mode.element.player)); } if(mode.skill){ for(var i in mode.skill){ lib.skill[i]=mode.skill[i]; } } if(mode.card){ for(var i in mode.card){ lib.card[i]=mode.card[i]; } } game.finishCards(); if(mode.characterPack){ for(var i in mode.characterPack){ lib.characterPack[i]=mode.characterPack[i]; } } _status.event=lib.element.GameEvent.initialGameEvent(); _status.paused=false; game.createEvent('game',false).setContent(lib.init.startOnline); game.loop(); game.send('inited'); ui.create.connecting(true); }); } if(_status.event.parent){ game.forceOver('noover',proceed); } else{ proceed(); } for(var i in lib.characterPack){ for(var j in lib.characterPack[i]){ lib.character[j]=lib.character[j]||lib.characterPack[i][j]; } } }, reinit:function(config,state,state2,ip,observe,onreconnect,cardtag,postReconnect){ ui.auto.show(); ui.pause.show(); game.clearConnect(); clearTimeout(_status.createNodeTimeout); game.online=true; game.ip=ip; game.servermode=state.servermode; game.roomId=state.roomId; if(state.over){ _status.over=true; } if(observe){ game.observe=true; game.onlineID=null; game.roomId=null; } if(game.servermode&&!observe){ game.saveConfig('reconnect_info',[_status.ip,game.onlineID,game.roomId]); } else{ game.saveConfig('reconnect_info',[_status.ip,game.onlineID]); if(!observe){ game.saveConfig('tmp_user_roomId',game.roomId); } } _status.connectMode=true; lib.configOL=config; lib.playerOL={}; lib.cardOL={}; game.loadModeAsync(config.mode,function(mode){ for(var i in mode.ai){ if(typeof mode.ai[i]=='object'){ if(ai[i]==undefined) ai[i]={}; for(var j in mode.ai[i]){ ai[i][j]=mode.ai[i][j]; } } else{ ai[i]=mode.ai[i]; } } for(var i in mode.get){ if(typeof mode.get[i]=='object'){ if(get[i]==undefined) get[i]={}; for(var j in mode.get[i]){ get[i][j]=mode.get[i][j]; } } else{ get[i]=mode.get[i]; } } for(var i in mode.translate){ lib.translate[i]=mode.translate[i]; } if(mode.game){ game.getIdentityList=mode.game.getIdentityList; game.getIdentityList2=mode.game.getIdentityList2; game.updateState=mode.game.updateState; game.showIdentity=mode.game.showIdentity; } if(mode.element&&mode.element.player){ Object.defineProperties(lib.element.Player.prototype,Object.getOwnPropertyDescriptors(mode.element.player)); } if(mode.skill){ for(var i in mode.skill){ lib.skill[i]=mode.skill[i]; } } if(mode.card){ for(var i in mode.card){ lib.card[i]=mode.card[i]; } } game.finishCards(); if(mode.characterPack){ for(var i in mode.characterPack){ lib.characterPack[i]=mode.characterPack[i]; } } if(mode.onreinit){ mode.onreinit(); } _status.cardtag=get.parsedResult(cardtag); game.players=[]; game.dead=[]; for(var i in lib.characterPack){ for(var j in lib.characterPack[i]){ lib.character[j]=lib.character[j]||lib.characterPack[i][j]; } } game.clearArena(); game.finishCards(); if(!observe){ ui.create.chat(); if(ui.exitroom){ ui.exitroom.remove(); delete ui.exitroom; } } else{ if(!ui.exitroom){ ui.create.system('退出旁观',function(){ game.saveConfig('reconnect_info'); game.reload(); },true); } if(!lib.configOL.observe_handcard){ ui.arena.classList.add('observe'); } } postReconnect=get.parsedResult(postReconnect); for(var i in postReconnect){ if(Array.isArray(postReconnect[i])){ postReconnect[i].shift().apply(this,postReconnect[i]); } } state=get.parsedResult(state); ui.arena.setNumber(state.number); _status.mode=state.mode; _status.renku=state.renku; lib.inpile=state.inpile; lib.inpile_nature=state.inpile_nature; var pos=state.players[observe||game.onlineID].position; for(var i in state.players){ var info=state.players[i]; var player=ui.create.player(ui.arena).animate('start'); player.dataset.position=(info.position`${get.prefixSpan('SP')}` }], ['☆SP',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('SP')}` }], ['J.SP',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('SP')}` }], ['K系列',{ showName:'K', }], ['经典',{ showName:'典', }], ['君',{ color:'#fefedc', nature:'shenmm', }], ['骰子',{ getSpan:()=>{ const span=document.createElement('span'); span.style.fontFamily='NonameSuits'; span.textContent='🎲'; return span.outerHTML; } }], ['SP',{ getSpan:()=>{ const span=document.createElement('span'),style=span.style; style.writingMode=style.webkitWritingMode='horizontal-tb'; style.fontFamily='MotoyaLMaru'; style.transform='scaleY(0.85)'; span.textContent='SP'; return span.outerHTML; }, }], ['OL',{ getSpan:()=>{ const span=document.createElement('span'),style=span.style; style.writingMode=style.webkitWritingMode='horizontal-tb'; style.fontFamily='MotoyaLMaru'; style.transform='scaleY(0.85)'; span.textContent='OL'; return span.outerHTML; }, }], ['RE',{ getSpan:()=>{ const span=document.createElement('span'),style=span.style; style.writingMode=style.webkitWritingMode='horizontal-tb'; style.fontFamily='MotoyaLMaru'; style.transform='scaleY(0.85)'; span.textContent='RE'; return span.outerHTML; }, }], ['手杀',{ getSpan:(prefix,name)=>{ const simple=lib.config.buttoncharacter_prefix=='simple',span=document.createElement('span'); if(lib.characterPack.shiji&&name in lib.characterPack.shiji){ for(const entry of Object.entries(lib.characterSort.shiji)){ if(!entry[1].includes(name)) continue; prefix=get.translation(entry[0]).slice(-1); break; } if(!simple){ span.style.color='#def7ca'; span.dataset.nature='watermm'; } span.innerHTML=prefix; } else if(simple) span.textContent='手杀'; else{ span.style.fontFamily='NonameSuits'; span.textContent='📱'; } return span.outerHTML; }, }], ['TW',{ getSpan:()=>{ const span=document.createElement('span'),style=span.style; style.writingMode=style.webkitWritingMode='horizontal-tb'; style.fontFamily='MotoyaLMaru'; style.transform='scaleY(0.85)'; span.textContent='TW'; return span.outerHTML; }, }], ['TW神',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('TW')}${get.prefixSpan('神')}` }], ['TW将',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('TW')}${get.prefixSpan('将')}` }], ['OL神',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('OL')}${get.prefixSpan('神')}` }], ['旧神',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('旧')}${get.prefixSpan('神')}` }], ['旧晋',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('旧')}${get.prefixSpan('晋')}` }], ['新杀SP',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('新杀')}${get.prefixSpan('SP')}` }], ['界SP',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('界')}${get.prefixSpan('SP')}` }], ['S特神',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('★')}${get.prefixSpan('神')}` }], ['手杀界',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('手杀')}${get.prefixSpan('界')}` }], ['战役篇神',{ /** * @returns {string} */ getSpan:()=>`${get.prefixSpan('战役篇')}${get.prefixSpan('神')}` }], ['星',{ color:'#ffd700', nature:'glodenmm', }] ]), groupnature:{ shen:'shen', wei:'water', shu:'soil', wu:'wood', qun:'qun', western:'thunder', key:'key', jin:'thunder', ye:'thunder', }, lineColor:new Map([ ['fire',[255,146,68]], ['yellow',[255,255,122]], ['blue',[150,202,255]], ['green',[141,255,216]], ['ice',[59,98,115]], ['thunder',[141,216,255]], ['kami',[90,118,99]], ['white',[255,255,255]], ['poison',[104,221,127]], ['brown',[195,161,223]], ['legend',[233,131,255]] ]), phaseName:['phaseZhunbei','phaseJudge','phaseDraw','phaseUse','phaseDiscard','phaseJieshu'], quickVoice:[ '我从未见过如此厚颜无耻之人!', '这波不亏', '请收下我的膝盖', '你咋不上天呢', '放开我的队友,冲我来', '你随便杀,闪不了算我输', '见证奇迹的时刻到了', '能不能快一点啊,兵贵神速啊', '主公,别开枪,自己人', '小内再不跳,后面还怎么玩儿啊', '你们忍心,就这么让我酱油了?', '我,我惹你们了吗', '姑娘,你真是条汉子', '三十六计,走为上,容我去去便回', '人心散了,队伍不好带啊', '昏君,昏君啊!', '风吹鸡蛋壳,牌去人安乐', '小内啊,您老悠着点儿', '不好意思,刚才卡了', '你可以打得再烂一点吗', '哥们,给力点儿行嘛', '哥哥,交个朋友吧', '妹子,交个朋友吧', ], other:{ ignore:()=>void 0 } }; const game={ //Stratagem //谋攻 setStratagemBuffCost:(cardName,cost)=>game.broadcastAll((clientCardName,clientCost)=>lib.stratagemBuff.cost.set(clientCardName,clientCost),cardName,cost), setStratagemBuffEffect:(cardName,effect)=>game.broadcastAll((clientCardName,clientEffect)=>lib.stratagemBuff.cost.set(clientCardName,clientEffect),cardName,effect), setStratagemBuffPrompt:(cardName,prompt)=>game.broadcastAll((clientCardName,clientPrompt)=>lib.stratagemBuff.cost.set(clientCardName,clientPrompt),cardName,prompt), //添加新的属性杀 addNature:(nature,translation,config)=>{ if(!nature) throw new TypeError(); if(translation&&translation.length) lib.translate['nature_'+nature]=translation; game.callHook("addNature",[nature,translation,config]); return nature; }, //判断卡牌信息/事件是否有某个属性 hasNature:(item,nature,player)=>{ var natures=get.natureList(item,player); if(!nature) return natures.length>0; if(nature=='linked') return natures.some(n=>lib.linked.includes(n)); return get.is.sameNature(natures,nature); }, //设置卡牌信息/事件的属性 setNature:(item,nature,addNature)=>{ if(!nature) nature=[]; if(!addNature){ item.nature=get.nature(nature); if(!item.nature.length) delete item.nature; } else{ let natures=Array.isArray(nature)?nature:nature.split(lib.natureSeparator); let _nature=get.natureList(item,false); _nature.addArray(natures); item.nature=_nature.join(lib.natureSeparator); } return item.nature; }, //洗牌 washCard:()=>{ if(!ui.cardPile.hasChildNodes()&&!ui.discardPile.hasChildNodes()) return false; if(_status.maxShuffle!=undefined){ if(_status.maxShuffle==0){ if(_status.maxShuffleCheck){ game.over(_status.maxShuffleCheck()); } else{ game.over('平局'); } return []; } _status.maxShuffle--; } game.shuffleNumber++; const cards=Array.from(ui.cardPile.childNodes); if(_status.discarded){ _status.discarded.length=0; } for(let i=0;i{ if(!id) throw new TypeError(); if(lib.comparator.typeEquals(short,"object")){ config=short; short=null; } if(lib.comparator.typeEquals(name,"object")){ config=name; name=null; } if(!lib.comparator.typeEquals(short,"string")&&short){ name=short; } lib.group.add(id); if(short)lib.translate[id] = short; if(name)lib.translate[`${id}2`] = name; game.callHook("addGroup",[id,short,name,config]); return id; }, //通用的调用钩子函数 callHook:(name,args)=>{ const callHook=()=>{ for(const hook of lib.hooks[name]){ if(hook!=null&&typeof hook=="function"){ hook(...args); } } } if ("onload" in lib) lib.onload.add(callHook); else callHook(); }, //Yingbian //应变 yingbianEffect:function(event,content){ const yingbianEffect=game.createEvent('yingbianEffect'); yingbianEffect.player=event.player; yingbianEffect.card=event.card; yingbianEffect._trigger=event; yingbianEffect.setContent(content); yingbianEffect._args=Array.from(arguments); return yingbianEffect; }, setYingbianConditionColor:(yingbianCondition,color)=>game.broadcastAll((yingbianCondition,color)=>lib.yingbian.condition.color.set(yingbianCondition,color),yingbianCondition,color), setComplexYingbianCondition:(yingbianCondition,condition)=>game.broadcastAll((yingbianCondition,condition)=>lib.yingbian.condition.complex.set(yingbianCondition,condition),yingbianCondition,condition), setSimpleYingbianCondition:(yingbianCondition,condition)=>game.broadcastAll((yingbianCondition,condition)=>lib.yingbian.condition.simple.set(yingbianCondition,condition),yingbianCondition,condition), setYingbianEffect:(yingbianEffect,effect)=>game.broadcastAll((yingbianEffect,effect)=>lib.yingbian.effect.set(yingbianEffect,effect),yingbianEffect,effect), setYingbianPrompt:(yingbian,prompt)=>game.broadcastAll((yingbian,prompt)=>lib.yingbian.prompt.set(yingbian,prompt),yingbian,prompt), /** * Dynamic Style Manager * 动态CSS管理对象 * * > No idea to write, it's just a tool to handle css. * > 暂时不知道写啥,反正就是个管CSS的工具 * * @example * // 为符合".content"的元素增加"text-align: center"的样式 * game.dynamicStyle.add(".content", { * textAlign: "center" * }); * * // 在上一条的基础上,再为".content"增加"color: #FFFFFF"的样式 * game.dynamicStyle.add(".content", { * color: "#FFFFFF" * }); * * @example * // 批量添加符合对应选择器元素的样式 * game.dynamicStyle.addObject({ * ".content": { * textAlign: "center" * }, * ".ansory": { * fontSize: "16px" * } * }); * * @example * // 移除".content"元素的样式 * game.dynamicStyle.remove(".content"); * * @example * // 移除".content"元素的"textAlign"样式 * game.dynamicStyle.removeStyles(".content", ["textAligh"]); * * @example * // 如果".content"元素的样式存在,则将".content"的样式修改为给定的样式 * // 反之效果同`game.dynamicStyle.add` * game.dynamicStyle.update(".content", { * textAlign: "center" * }); */ dynamicStyle:new class{ /** * Object of style * 表示样式的对象 * * @typedef {Record} StyleObject */ /** * Rule to record style info. * 用于记录样式信息的规则 * * @typedef {[string, StyleObject]} Rule */ /** * Type used to declare the place to store css info. * 用来存CSS信息的空间的类型 * * @typedef {object} DynamicStyleCache * @property {Rule[]} rules 记录的规则 * @property {HTMLStyleElement} style 全局Style标签 * @property {CSSStyleSheet} sheet Style标签的Sheet */ /** * Initialize dynamicStyle. * 初始化数据 */ constructor(){ /** * @type {DynamicStyleCache} */ let cache=Object.create(null); cache.rules=new Array; cache.style=document.createElement("style"); cache.style.id="game.dynamicStyle"; document.head.appendChild(cache.style); cache.sheet=cache.style.sheet; /** * Place to store css info. * 存CSS信息的空间 * * @type {DynamicStyleCache} */ this._cache=cache; } /** * Turn the Object Style to string format. * 将给定的对象样式转换成字符串的形式 * * @param {StyleObject} style 给定的对象样式 * @returns {string} 样式的字符串形式 */ translate(style){ return Object.entries(style).map(item => `${item[0].replace(/([A-Z])/g, match => `-${match.toLowerCase()}`)}: ${item[1]};`).join(" "); } /** * Generate the common css selector. * 生成标准的CSS样式 * * @param {string} name 选择器 * @param {StyleObject} style 对象样式 * @returns {string} 标准的CSS样式 */ generate(name, style){ return `${name} { ${this.translate(style)} }`; } /** * Determine the selector is in rules. * 检查是否存在对应选择器的规则 * * @param {string} name 选择器 * @returns {boolean} */ has(name){ return this._cache.rules.some(item=>item[0]==name); } /** * Get the style of given selector, or return null. * 获得对应选择器的样式对象,若不存在,则返回`null` * * @param {string} name 选择器 * @returns {?StyleObject} */ get(name){ const result = this.find(item=>item[0]==name); return result ? result[1] : null; } /** * Callback of `DynamicStyle#find`, getting the rule wanted. * `DynamicStyle#find`的回调函数,用于获取符合要求的规则 * * @callback FindCallback * @param {Rule} rule 样式规则 * @param {number} index 样式编号 * @param {Rule[]} rules 规则集 * @returns {boolean} */ /** * Get the rule wanted by given function. * 通过给定的函数,获取符合要求的规则 * * @param {FindCallback} fn 用于检查的函数 * @returns {?StyleObject} */ find(fn){ return this._cache.rules.find(fn); } /** * Length of rules. * 规则集的长度 * * @returns {number} */ size(){ return this._cache.rules.length; } /** * Get the index of given selector, or return `-1`. * 获得对应选择器的位置,若不存在,则返回`-1` * * @param {string} name 选择器 * @returns {number} */ indexOf(name){ for (let i=0;i} object 以`name: style`存储的映射 * @returns {boolean} 添加的结果,为`true`则添加成功,为`false`则添加失败 */ addObject(object){ return Object.entries(object).map(item => this.add(item[0],item[1])); } /** * @param {string} name 要移除规则的选择器 * @returns {boolean} 移除的结果,为`true`则移除成功,为`false`则移除失败 */ remove(name){ if(!this.has(name)) return false; try{ const index=this.indexOf(name); this._cache.rules.splice(index,1); this._cache.sheet.deleteRule(index); return true; } catch(e){ console.log(e); return false; } } /** * @param {string} name 要移除规则的选择器 * @param {string[]} styles 要移除的样式 * @returns {boolean} 移除的结果,为`true`则移除成功,为`false`则移除失败 */ removeStyles(name,styles){ if(!this.has(name)) return false; const style=this.get(name); styles.forEach(styleName=>{ delete style[styleName]; }); return this.update(name,style); } /** * 添加或修改一个规则所对应的样式 * * @param {string} name 要变更规则的选择器 * @param {StyleObject} style 变更规则的样式 * @returns {boolean} 更新的结果,为`true`则更新成功,为`false`则更新失败 */ update(name,style){ try{ if(this.has(name)){ const index=this.indexOf(name); this._cache.sheet.deleteRule(index); this._cache.sheet.insertRule(this.generate(name,style),index); this._cache.rules[index] = [name, style]; }else{ const index=this._cache.rules.length; this._cache.rules.push([name,style]); this._cache.sheet.insertRule(this.generate(name,style),index); } return true; } catch(e){ console.log(e); return false; } } }, //Add a background music to the config option //在设置选项中添加一首背景音乐 addBackgroundMusic:(link,musicName,aozhan)=>{ const backgroundMusicSetting=ui[aozhan?'aozhan_bgm':'background_music_setting'],menu=backgroundMusicSetting._link.menu,config=backgroundMusicSetting._link.config; if(typeof musicName!='string') musicName=link; if(aozhan) lib.mode.guozhan.config.aozhan_bgm.item[link]=musicName; else lib.config.all.background_music.add(link); config.item[link]=musicName; const textMenu=ui.create.div('',musicName,menu,function(){ const node=this.parentNode._link,config=node._link.config; node._link.current=this.link; const tmpName=node.lastChild.innerHTML; node.lastChild.innerHTML=config.item[this._link]; if(config.onclick&&config.onclick.call(node,this._link,this)===false) node.lastChild.innerHTML=tmpName; if(config.update) config.update(); },menu.childElementCount-2); textMenu._link=link; config.updatex.call(backgroundMusicSetting,[]); }, //Remove a background music from the config option //从设置选项中移除一首背景音乐 removeBackgroundMusic:(link,aozhan)=>{ if(aozhan){ if(['disabled','random'].includes(link)) return; delete lib.mode.guozhan.config.aozhan_bgm.item[link]; if(!Array.isArray(_status.aozhanBGMToRemove)) _status.aozhanBGMToRemove=[]; _status.aozhanBGMToRemove.add(link); } else{ if(['music_off','music_custom','music_random'].includes(link)) return; lib.config.all.background_music.remove(link); } const backgroundMusicSetting=ui[aozhan?'aozhan_bgm':'background_music_setting'],config=backgroundMusicSetting._link.config; config.updatex.call(backgroundMusicSetting,[]); }, updateBackground:()=>{ const background=_status.tempBackground||lib.config.image_background; ui.background.delete(); const uiBackground=ui.background=ui.create.div('.background'),style=uiBackground.style; if(lib.config.image_background_blur){ style.filter='blur(8px)'; style.webkitFilter='blur(8px)'; style.transform='scale(1.05)'; } document.body.insertBefore(uiBackground,document.body.firstChild); if(background.startsWith('db:')) uiBackground.setBackgroundDB(background.slice(3)); else if(background.startsWith('ext:')) uiBackground.setBackgroundImage(`extension/${background.slice(4)}`); else if(background=='default'){ uiBackground.animate('start'); style.backgroundImage='none'; } else if(background.startsWith('custom_')){ style.backgroundImage='none'; game.getDB('image',background).then(fileToLoad=>{ if(!fileToLoad) return; const fileReader = new FileReader(); fileReader.onload=fileLoadedEvent=>style.backgroundImage=`url(${fileLoadedEvent.target.result})`; fileReader.readAsDataURL(fileToLoad, "UTF-8"); }); } else uiBackground.setBackgroundImage(`image/background/${background}.jpg`); style.backgroundSize='cover'; style.backgroundPosition='50% 50%'; }, //Generate a beatmap using the given BPM, beats, and offset //用给定的BPM、节拍和偏移生成谱面 generateBeatmapTimeleap:(bpm,beats,offset)=>beats.map(value=>Math.round(value*60000/bpm+(offset||0))), updateRenku:function(){ game.broadcast(function(renku){ _status.renku=renku; },_status.renku); for(var i of game.players){ if(i.storage.renku) i.markSkill('renku'); } }, loseAsync:function(arg){ var next=game.createEvent('loseAsync'); next.forceDie=true; next.getd=function(player,key,position){ if(!position) position=ui.discardPile; if(!key) key='cards'; var cards=[],event=this; game.checkGlobalHistory('cardMove',function(evt){ if(evt.name!='lose'||evt.position!=position||evt.getParent()!=event) return; if(player&&player!=evt.player) return; cards.addArray(evt[key]); }); return cards; }; next.getl=function(player){ const that=this; const map={ player:player, hs:[], es:[], js:[], ss:[], xs:[], cards:[], cards2:[], gaintag_map:{}, }; player.checkHistory('lose',function(evt){ if(evt.parent==that){ map.hs.addArray(evt.hs); map.es.addArray(evt.es); map.js.addArray(evt.js); map.ss.addArray(evt.ss); map.xs.addArray(evt.xs); map.cards.addArray(evt.cards); map.cards2.addArray(evt.cards2); for(let key in evt.gaintag_map){ if(!map.gaintag_map[key]) map.gaintag_map[key]=[]; map.gaintag_map[key].addArray(evt.gaintag_map[key]); } } }); return map; }; next.getg=function(player){ var that=this; var cards=[]; player.checkHistory('gain',function(evt){ if(evt.parent==that){ cards.addArray(evt.cards); } }); return cards; }; if(arg&&get.is.object(arg)){ for(var i in arg) next[i]=arg[i]; } return next; }, callFuncUseStepCache:function(prefix,func,params){ if(typeof func != 'function')return; if(_status.closeStepCache || !_status.event)return func.apply(null,params); var cacheKey = "["+prefix+"]"+get.paramToCacheKey.apply(null,params); var ret = _status.event.getStepCache(cacheKey); if(ret === undefined || ret === null){ ret = func.apply(null,params); _status.event.putStepCache(cacheKey,ret); } return ret; }, getRarity:function(name){ var rank=lib.rank.rarity; if(rank.legend.contains(name)) return 'legend'; if(rank.epic.contains(name)) return 'epic'; if(rank.rare.contains(name)) return 'rare'; if(get.mode()!='chess'&&rank.junk.contains(name)) return 'junk'; return 'common'; }, hasGlobalHistory:function(key,filter,last){ if(!key) return _status.globalHistory[_status.globalHistory.length-1]; if(!filter) return _status.globalHistory[_status.globalHistory.length-1][key]; else{ const history=game.getGlobalHistory(key); if(last){ const lastIndex=history.indexOf(last); return history.some((event,index)=>{ if(index>lastIndex) return false; return filter(event); }); } else{ return history.some(filter); } } }, checkGlobalHistory:function(key,filter,last){ if(!key) return _status.globalHistory[_status.globalHistory.length-1]; if(!filter) return _status.globalHistory[_status.globalHistory.length-1][key]; else{ const history=game.getGlobalHistory(key); if(last){ const lastIndex=history.indexOf(last); history.forEach((event,index)=>{ if(index>lastIndex) return false; return filter(event); }); } else{ history.forEach(filter); } } }, getGlobalHistory:function(key,filter,last){ if(!key) return _status.globalHistory[_status.globalHistory.length-1]; if(!filter) return _status.globalHistory[_status.globalHistory.length-1][key]; else{ const history=game.getGlobalHistory(key); if(last){ const lastIndex=history.indexOf(last); return history.filter((event,index)=>{ if(index>lastIndex) return false; return filter(event); }) } return history.filter(filter); } }, hasAllGlobalHistory:function(key,filter,last){ if(!key||!filter) return; let stopped=false; _status.globalHistory.forEach(value=>{ if(value[key]){ if(last&&value[key].includes(last)&&!stopped){ stopped=true; const lastIndex=value[key].indexOf(last); if(value[key].some((event,index)=>{ if(index>lastIndex) return false; return filter(event); })) return true; } else{ if(value[key].some(filter)) return true; } } }) }, checkAllGlobalHistory:function(key,filter,last){ if(!key||!filter) return; let stopped=false; _status.globalHistory.forEach(value=>{ if(value[key]){ if(last&&value[key].includes(last)&&!stopped){ stopped=true; const lastIndex=value[key].indexOf(last); value[key].forEach((event,index)=>{ if(index>lastIndex) return false; return filter(event); }); } else{ value[key].forEach(filter); } } }) }, getAllGlobalHistory:function(key,filter,last){ const history=[]; _status.globalHistory.forEach(value=>{ if(!key||!value[key]){ history.push(value); } else{ history.push(...value[key]); } }) if(filter){ if(last){ const lastIndex=history.indexOf(last); return history.filter(function(event,index){ if(index>lastIndex) return false; return filter(event); }); } return history.filter(filter); } return history; }, cardsDiscard:function(cards){ var type=get.itemtype(cards); if(type!='cards'&&type!='card') return; var next=game.createEvent('cardsDiscard'); next.cards=type=='cards'?cards.slice(0):[cards]; next.setContent('cardsDiscard'); next.getd=function(player,key,position){ return this.cards.slice(0); }; return next; }, cardsGotoOrdering:function(cards){ var type=get.itemtype(cards); if(type!='cards'&&type!='card') return; var next=game.createEvent('cardsGotoOrdering'); next.cards=type=='cards'?cards.slice(0):[cards]; next.setContent('cardsGotoOrdering'); return next; }, cardsGotoSpecial:function(cards,bool){ var type=get.itemtype(cards); if(type!='cards'&&type!='card') return; var next=game.createEvent('cardsGotoSpecial'); next.cards=type=='cards'?cards.slice(0):[cards]; if(bool=='toRenku') next.toRenku=true; else if(bool===false) next.notrigger=true; next.setContent('cardsGotoSpecial'); return next; }, cardsGotoPile:function(){ const cards=[]; const next=game.createEvent('cardsGotoPile'); next.cards=cards; for(let i=0;i{ game.addVideo('changeLand',player,url); const parsedPath=lib.path.parse(url); delete parsedPath.base; if(!parsedPath.dir) parsedPath.dir='image/card/'; if(!parsedPath.ext) parsedPath.ext='.jpg'; const fileName=parsedPath.name; game.broadcastAll((formattedPath,name,skill,player)=>{ const node=ui.create.div('.background.upper.land'); node.setBackgroundImage(formattedPath); node.destroy=()=>{ if (node.skill) { game.removeGlobalSkill(node.skill); if(node.system) node.system.remove(); } node.classList.add('hidden'); setTimeout(()=>node.remove(),3000); if(ui.land==node) ui.land=null; } if(ui.land){ document.body.insertBefore(node,ui.land); ui.land.destroy(); } else{ node.classList.add('hidden'); document.body.insertBefore(node,ui.window); ui.refresh(node); node.classList.remove('hidden'); } ui.land=node; if(!name) return; node.name=name; node.skill=skill; if(player){ node.player=player; player.addTempSkill('land_used'); } lib.setPopped(node.system=ui.create.system(lib.translate[skill],null,true,true),()=>{ const uiIntro=ui.create.dialog('hidden'); uiIntro.addText(player?`来源:${get.translation(player)}`:'地图').style.margin='0'; uiIntro._place_text=uiIntro.add(ui.create.div('.text',lib.translate[`${skill}_info`])); uiIntro.add(ui.create.div('.placeholder.slim')); return uiIntro; },200); game.addGlobalSkill(skill); },lib.path.format(parsedPath),fileName,`${fileName}_skill`,player); }, checkFileList:function(updates,proceed){ var n=updates.length; if(!n){ proceed(n); } for(var i=0;i(func: T, ...args: Parameters) => void; * (func: (...args: T) => void, ...args: T) => void; * }} */ broadcast:function(){ if(!lib.node||!lib.node.clients||game.online) return; for(var i=0;i(func: T, ...args: Parameters) => void; * (func: (...args: T) => void, ...args: T) => void; * }} */ broadcastAll:function(){ if(game.online) return; var argc=arguments.length; var args=new Array(argc); for(var i=0;inew lib.element.Client(new lib.element.NodeWS(id)).send(message), createServer:function(){ lib.node.clients=[]; lib.node.banned=[]; lib.node.observing=[]; lib.node.torespond={}; lib.node.torespondtimeout={}; lib.playerOL={}; lib.cardOL={}; lib.wsOL={}; ui.create.roomInfo(); ui.create.chat(); if(game.onlineroom){ } else{ var WebSocketServer=require('ws').Server; var wss=new WebSocketServer({port:8080}); game.ip=get.ip(); wss.on('connection',lib.init.connection); } }, playAudio:function(){ let path='',emptyPath=true,notCheckDBPath=true,onError=null; if(_status.video){ if(arguments[1]!='video') return; path=arguments[0]; } else{ for(const argument of arguments){ if(typeof argument==='string'||typeof argument=='number'){ if(emptyPath) emptyPath=false; else if(notCheckDBPath){ notCheckDBPath=false; if(/^db:extension-[^:]*$/.test(path)) path+=':'; else path+='/'; } else path+='/'; path+=argument; } else if(typeof argument=='function') onError=argument; if(_status.video) break; } if(path.startsWith('ext:')) path=path.replace(/^ext:/,'extension/'); else if(!path.startsWith('db:')) path=`audio/${path}`; if(!lib.config.repeat_audio&&_status.skillaudio.contains(path)) return; } _status.skillaudio.add(path); game.addVideo('playAudio',null,path); setTimeout(()=>_status.skillaudio.remove(path),1000); const audio=document.createElement('audio'); audio.autoplay=true; audio.volume=lib.config.volumn_audio/8; audio.addEventListener('ended',()=>audio.remove()); audio.onerror=event=>{ audio.remove(); if(onError) onError(event); }; //Some browsers do not support "autoplay", so "oncanplay" listening has been added audio.oncanplay=()=>Promise.resolve(audio.play()).catch(()=>void 0); new Promise((resolve,reject)=>{ if(path.startsWith('db:')) game.getDB('image',path.slice(3)).then(octetStream=>resolve(get.objectURL(octetStream)),reject); else if(lib.path.extname(path)) resolve(`${lib.assetURL}${path}`); else resolve(`${lib.assetURL}${path}.mp3`); }).then(resolvedPath=>{ audio.src=resolvedPath; ui.window.appendChild(audio); }); return audio; }, /** * 根据skill中的audio,audioname,audioname2和player来获取音频地址列表 * @param {String} skill 技能名 * @param {Player|String} player 角色/角色名 * @returns {Array} 分析完的语音地址列表 */ parseSkillAudio:function(skill,player){ if(typeof player=='string') player={name:player}; else if(get.itemtype(player)!='player') player={}; /** * 处理 audioInfo 外的参数 * @param {String} skill 技能名 * @param {Player|{name:string}} player 角色 * @param {Array} audioname audioname历史 * @param {Array} history 判断deadlock * @param {Number} fixedNum [audioname, number] 中的第二个参数,用来限制语音数 * @returns {Array} 音频地址数组(有需要playSkillAudio的为[skillname]) */ function getAudioList(skill,player,audioname,history,fixedNum){ let info=lib.skill[skill]; if(!info) return []; if(!history) history=[]; if(history.includes(skill)){//判断deadlock console.trace(`${skill} in ${history} forms a deadlock`); if(info.audio!==false) return [[skill]]; return []; } history.push(skill); let audioInfo=info.audio; if(info.audioname2){ if(info.audioname2[player.name]) audioInfo=info.audioname2[player.name]; else if(info.audioname2[player.name1]) audioInfo=info.audioname2[player.name1]; else if(info.audioname2[player.name2]) audioInfo=info.audioname2[player.name2]; } if(typeof audioInfo=='function') audioInfo=audioInfo(player); if(!audioname) audioname=[]; if(Array.isArray(info.audioname)) audioname.addArray(info.audioname); let audioList=parseAudio(skill,audioInfo,audioname,player,history,fixedNum); if(fixedNum&&fixedNum} audioname 要判断的audioname * @param {Player|{name:string}} player 角色 * @param {Array} history 判断deadlock * @param {Number} fixedNum [audioname, number] 中的第二个参数,用来限制语音数 * @returns {Array} 音频地址数组(有需要playSkillAudio的为[skillname]) */ function parseAudio(skill,audioInfo,audioname,player,history,fixedNum){ if(Array.isArray(audioInfo)){ if(typeof audioInfo[0]=='string'&&typeof audioInfo[1]=='number'){// [audioname, number] if(lib.skill[audioInfo[0]]) return getAudioList(audioInfo[0],player,audioname,history,fixedNum||audioInfo[1]); return parseAudio(audioInfo[0],audioInfo[1],audioname,player,history,fixedNum||audioInfo[1]); } return audioInfo.reduce((total,i)=>total.addArray(parseAudio(skill,i,audioname,player,history,fixedNum)),[]); } if(!['string','number','boolean'].includes(typeof audioInfo)) return []; if(audioInfo===false) return []; if(typeof audioInfo=='string'&&lib.skill[audioInfo]) return getAudioList(audioInfo,player,audioname,history,fixedNum); let audioList=[]; audioInfo=String(audioInfo); let list=audioInfo.match(/(?:(.*):|^)(true|\d*)(?::(.*)|$)/); if(list&&list[2]){ let _audioname=''; if(audioname.includes(player.name)) _audioname=`_${player.name}`; else if(audioname.includes(player.name1)) _audioname=`_${player.name1}`; else if(audioname.includes(player.name2)) _audioname=`_${player.name2}`; list=list.slice(1);//[路径,number/true,格式] if(list[1]=='true') audioList.add(`${list[0]||'skill'}/${skill}${_audioname}.${list[2]||'mp3'}`); else{ list[1]=parseInt(list[1]); for(let i=1;i<=list[1];i++){ audioList.add(`${list[0]||'skill'}/${skill}${_audioname}${i}.${list[2]||'mp3'}`); } } } else audioList.add(`${/(?:^db:|^ext:|\/)/.test(audioInfo)?'':'skill/'}${audioInfo}`); return audioList; } return getAudioList(skill,player); }, trySkillAudio:function(skill,player,directaudio,nobroadcast/*,index*/){ if(!nobroadcast) game.broadcast(game.trySkillAudio,skill,player,directaudio,nobroadcast/*,index*/); var info=get.info(skill); if(!info) return; if(!lib.config.background_speak) return; if(info.direct&&!directaudio) return; if(lib.skill.global.includes(skill)&&!lib.skill[skill].forceaudio) return; let list=game.parseSkillAudio(skill,player); if(!list.length) return; // if(index) index=index%list.length||list.length; // let audio=list[index?index-1:Math.floor(Math.random()*list.length)]; let audio=list[Math.floor(Math.random()*list.length)]; if(Array.isArray(audio)) return game.playSkillAudio(audio[0]); return game.playAudio(audio); }, playSkillAudio:function(name,index){ if(_status.video&&arguments[1]!='video') return; if(!lib.config.repeat_audio&&_status.skillaudio.includes(name)) return; game.addVideo('playSkillAudio',null,name); if(name.indexOf('|')void 0); }; ui.window.appendChild(audio); }, playCardAudio:function(card,sex){ if(typeof card === 'string'){ card = {name:card}; } if(get.itemtype(sex) === 'player'){ sex = (sex.sex == 'female'?'female':'male'); }else if(typeof sex == 'string'){ sex = (sex == 'female'?'female':'male'); } if(!lib.config.background_audio||get.type(card)=='equip'&&!lib.config.equip_audio) return; var nature=get.natureList(card)[0]; if(lib.natureAudio[card.name]){ let useAudio = lib.natureAudio[card.name][nature]; if(useAudio === 'default'){ game.playAudio('card',sex,`${card.name}_${nature}`); return; }else if(useAudio && useAudio[sex]){ game.playAudio(useAudio[sex]); return; } } const audio=lib.card[card.name].audio; if(typeof audio=='string'){ const audioInfo=audio.split(':'); if(audio.startsWith('db:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${card.name}_${sex}.${audioInfo[3]||'mp3'}`); else if(audio.startsWith('ext:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${card.name}_${sex}.${audioInfo[2]||'mp3'}`); else game.playAudio('card',sex,`${audioInfo[0]}.${audioInfo[1]||'mp3'}`); } else game.playAudio('card',sex,card.name); }, playBackgroundMusic:()=>{ if(lib.config.background_music=='music_off'){ ui.backgroundMusic.src=''; return; } if(_status._aozhan){ const aozhanBGMConfiguration=lib.config.mode_config.guozhan.aozhan_bgm; if(aozhanBGMConfiguration=='disabled') return; let aozhan=_status.tempAozhan||aozhanBGMConfiguration; if(Array.isArray(aozhan)) aozhan=aozhan.randomGet('disabled',_status.currentAozhan)||aozhanBGMConfiguration; if(aozhan=='random') aozhan=Object.keys(lib.mode.guozhan.config.aozhan_bgm.item).randomGet('disabled','random',_status.currentAozhan); _status.currentAozhan=aozhan; if(aozhan.startsWith('db:')) game.getDB('image',aozhan.slice(3)).then(result=>ui.backgroundMusic.src=result); else if(aozhan.startsWith('ext:')) ui.backgroundMusic.src=`${lib.assetURL}extension/${aozhan.slice(4)}`; else ui.backgroundMusic.src=`${lib.assetURL}audio/background/aozhan_${aozhan}.mp3`; return; } let music=_status.tempMusic||lib.config.background_music; if(Array.isArray(music)) music=music.randomGet('music_off',_status.currentMusic)||lib.config.background_music; if(music=='music_random') music=lib.config.all.background_music.randomGet('music_off','music_random',_status.currentMusic); _status.currentMusic=music; if(music=='music_custom'){ const backgroundMusicSourceConfiguration=lib.config.background_music_src; if(backgroundMusicSourceConfiguration) ui.backgroundMusic.src=backgroundMusicSourceConfiguration; return; } if(music.startsWith('db:')) game.getDB('image',music.slice(3)).then(result=>ui.backgroundMusic.src=result); else if(music.startsWith('ext:')) ui.backgroundMusic.src=`${lib.assetURL}extension/${music.slice(4)}`; else ui.backgroundMusic.src=`${lib.assetURL}audio/background/${music}.mp3`; }, import:function(type,content,url){ if(type=='extension'){ const promise=game.loadExtension(content); if(typeof _status.extensionLoading=="undefined")_status.extensionLoading=[]; _status.extensionLoading.add(promise); return promise; } else{ if(!lib.imported[type])lib.imported[type]={}; const promise=Promise.resolve((gnc.is.generator(content)?gnc.of(content):content)(lib,game,ui,get,ai,_status)).then(content2=>{ if(content2.name){ lib.imported[type][content2.name]=content2; delete content2.name; } }); if(typeof _status.importing=="undefined")_status.importing={}; if(!_status.importing[type])_status.importing[type]=[]; _status.importing[type].add(promise); return promise; } }, loadExtension:gnc.of(function*(object){ let noEval=false; if(typeof object=='function'){ object=yield (gnc.is.generatorFunc(object)?gnc.of(object):object)(lib,game,ui,get,ai,_status); noEval=true; } const name=object.name,extensionName=`extension_${name}`,extensionMenu=lib.extensionMenu[extensionName]={ enable:{ name:'开启', init:true } },objectPackage=object.package; if(objectPackage){ const author=Object.getOwnPropertyDescriptor(objectPackage,'author'); if(author) Object.defineProperty(extensionMenu.author={ get name(){ return `作者:${this.author}`; }, clear:true, nopointer:true, },'author',author); const intro=Object.getOwnPropertyDescriptor(objectPackage,'intro'); if(intro) Object.defineProperty(extensionMenu.intro={ clear:true, nopointer:true, },'name',intro); } const objectConfig=object.config; if(objectConfig) Object.defineProperties(extensionMenu,Object.keys(objectConfig).reduce((propertyDescriptorMap,key)=>{ propertyDescriptorMap[key]=Object.getOwnPropertyDescriptor(objectConfig,key); return propertyDescriptorMap; },{})); const help=object.help; if(help) Object.defineProperties(lib.help,Object.keys(help).reduce((propertyDescriptorMap,key)=>{ propertyDescriptorMap[key]=Object.getOwnPropertyDescriptor(help,key); return propertyDescriptorMap; },{})); if(object.editable!==false&&lib.config.show_extensionmaker) extensionMenu.edit={ name:'编辑此扩展', clear:true, onclick:()=>{ if(game.editExtension&&lib.extensionPack&&lib.extensionPack[name]) game.editExtension(name); else alert('无法编辑未启用的扩展,请启用此扩展并重启后重试'); } }; extensionMenu.delete={ name:'删除此扩展', clear:true, onclick:function(){ if(this.innerHTML!='确认删除'){ this.innerHTML='确认删除'; new Promise(resolve=>setTimeout(resolve,1000)).then(()=>this.innerHTML='删除此扩展'); return; } const page=this.parentNode,start=page.parentNode.previousSibling; page.remove(); if(start){ const pageInStart=Array.from(start.childNodes).find(childNode=>childNode.link==page); if(pageInStart){ let active=false; if(pageInStart.classList.contains('active')) active=true; pageInStart.remove(); if(active){ start.firstChild.classList.add('active'); start.nextSibling.appendChild(start.firstChild.link); } } } game.removeExtension(name); if(typeof object.onremove=='function') object.onremove(); } } if(_status.importingExtension){ game.importedPack=object; return; } const libConfig=lib.config; if(!object||!libConfig[`${extensionName}_enable`]) return; if(!noEval) lib.init.eval(object); const config=Object.keys(libConfig).reduce((constructingConfig,key)=>{ if(key!=extensionName&&key.startsWith(extensionName)) constructingConfig[key.slice(11+name.length)]=libConfig[key]; return constructingConfig; },{}); try{ let extensionPack=lib.extensionPack[name]; if(objectPackage){ extensionPack=lib.extensionPack[name]=objectPackage; objectPackage.files=object.files||{}; const extensionPackFiles=objectPackage.files; if(!extensionPackFiles.character) extensionPackFiles.character=[]; if(!extensionPackFiles.card) extensionPackFiles.card=[]; if(!extensionPackFiles.skill) extensionPackFiles.skill=[]; } else extensionPack=lib.extensionPack[name]={}; const content=object.content,precontent=object.precontent; extensionPack.code={ content:content, precontent:precontent, help:help, config:objectConfig } if(precontent){ _status.extension=name; yield (gnc.is.generatorFunc(precontent)?gnc.of(precontent):precontent).call(object,config); delete _status.extension; } if(content) lib.extensions.push([name,content,config,_status.evaluatingExtension,objectPackage||{}]); } catch(e){ console.log(e); } }), createDir:(directory,successCallback,errorCallback)=>{ const paths=directory.split('/').reverse(); if(window.resolveLocalFileSystemURL) return new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(lib.assetURL,resolve,reject)).then(directoryEntry=>{ const redo=entry=>new Promise((resolve,reject)=>entry.getDirectory(paths.pop(),{ create:true },resolve,reject)).then(resolvedDirectoryEntry=>{ if(paths.length) return redo(resolvedDirectoryEntry); if(typeof successCallback=='function') successCallback(); }); return redo(directoryEntry); },reason=>{ if(typeof errorCallback!='function') return Promise.reject(reason); errorCallback(reason); }); const fs=require("fs"); let path=__dirname; const redo=()=>{ path+=`/${paths.pop()}`; return new Promise(resolve=>fs.exists(path,resolve)).then(exists=>{ //不存在此目录 if(!exists) return new Promise(resolve=>fs.mkdir(path,resolve)); }).then(()=>{ if(paths.length) return redo(); if(typeof successCallback=='function') successCallback(); }); }; return redo(); }, importExtension:gnc.of(function*(data,finishLoad,exportExtension,extensionPackage){ //by 来瓶可乐加冰、Rintim、Tipx-L if(!window.JSZip) yield new Promise((resolve,reject)=>lib.init.js(`${lib.assetURL}game`,"jszip",resolve,reject)); const zip=new JSZip(); if(get.objtype(data)=='object'){ //导出 const _filelist=data._filelist,filelist2=_filelist||[]; if(_filelist) delete data._filelist; const filelist=Object.keys(data); filelist.forEach(value=>zip.file(value,data[value])); game.print(filelist); game.print(filelist2); const generate=zip.generate({ type:'arraybuffer' }); if(!exportExtension){ game.importExtension.apply(this,[generate,finishLoad]); return; } if(extensionPackage){ extensionPackage.files=filelist.concat(filelist2).filter(value=>value!='extension.js'); const size=generate.byteLength; if(size<1000) extensionPackage.size=`${size}B`; else if(size<1000000) extensionPackage.size=`${Math.round(size/1000)}KB`; else extensionPackage.size=`${Math.round(size/100000)/10}MB`; zip.file('package.js',Object.keys(extensionPackage).reduce((constructingData,key,currentIndex,keys)=>`${constructingData}\t${key}:${JSON.stringify(extensionPackage[key])}${currentIndex|\|/g,'-')}.zip`; if(lib.device){ const directory=lib.device=='android'?cordova.file.externalDataDirectory:cordova.file.documentsDirectory; new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(directory,resolve,reject)).then(directoryEntry=>new Promise((resolve,reject)=>directoryEntry.getFile(fileNameToSaveAs,{ create:true },resolve,reject))).then(fileEntry=>new Promise((resolve,reject)=>fileEntry.createWriter(resolve,reject))).then(fileWriter=>new Promise((resolve,reject)=>{ fileWriter.onerror=reject; fileWriter.onwriteend=resolve; fileWriter.write(blob); })).then(()=>alert(`文件已导出至${directory}${fileNameToSaveAs}`)); } else{ const downloadLink=document.createElement('a'); downloadLink.download=fileNameToSaveAs; downloadLink.innerHTML='Download File'; downloadLink.href=window.URL.createObjectURL(blob); downloadLink.click(); } if(typeof finishLoad=='function') finishLoad(); return; } //导入 const UHP=error=>alert(`导入失败:\n${JSON.stringify(error,null,'\t')}`); try{ zip.load(data); // alert(zip.file('文件夹/加扩展.js').asText()) const str=zip.file('extension.js').asText(); if(str===""||undefined) throw('你导入的不是扩展!请选择正确的文件'); _status.importingExtension=true; eval(str); yield Promise.allSettled(_status.extensionLoading); delete _status.extensionLoading; _status.importingExtension=false; if(!game.importedPack) throw('err'); const extensionName=game.importedPack.name; if(lib.config.all.plays.contains(extensionName)) throw('禁止安装游戏原生扩展'); const extensions=lib.config.extensions; if(extensions.contains(extensionName)) game.removeExtension(extensionName,true); extensions.add(extensionName); game.saveConfigValue('extensions'); game.saveConfig(`extension_${extensionName}_enable`,true); const config=game.importedPack.config; Object.keys(config).forEach(value=>{ const configObject=config[value]; if(configObject&&configObject.hasOwnProperty('init')) game.saveConfig(`extension_${extensionName}_${value}`,configObject.init); }); if(game.download){ const files=zip.files,hiddenFileFlags=['.','_'],fileList=Object.keys(files).filter(key=>!files[key].dir&&!hiddenFileFlags.includes(key[0])).reverse(); //alert(filelist) //电脑端 //具备nodeJS环境 if(lib.node&&lib.node.fs){ const writeFile=errnoException=>{ if(errnoException){ finishLoad(); UHP(errnoException); return; } if(fileList.length){ //filename 数组 ...dir+/+file //这里需要个创文件夹的函数 const zipDir=fileList.pop(),fileName=zipDir.split('/'),name=fileName.pop(),letGo=name=>new Promise(resolve=>lib.node.fs.writeFile(`${__dirname}/extension/${extensionName}/${name}`,zip.file(zipDir).asNodeBuffer(),null,resolve)).then(writeFile); return (fileName.length?game.createDir(`extension/${extensionName}/${fileName.join("/")}`).then(()=>letGo(`${fileName.join('/')}/${name}`)):letGo(name)); } finishLoad(); } game.ensureDirectory(`extension/${extensionName}`).then(writeFile).catch(UHP); } else new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(lib.assetURL,resolve,reject)).then(directoryEntry=>new Promise((resolve,reject)=>directoryEntry.getDirectory(`extension/${extensionName}`,{ create:true },resolve,reject))).then(directoryEntry=>{ //扩展文件夹 const writeFile=()=>{ if(!fileList.length){ finishLoad(); return; } //filename 数组 ...dir+/+file const zipDirectory=fileList.shift(),fileName=zipDirectory.split("/"),name=fileName.pop(),letGo=name=>new Promise((resolve,reject)=>directoryEntry.getFile(name,{ create:true },resolve,reject)).then(fileEntry=>new Promise((resolve,reject)=>fileEntry.createWriter(resolve,reject))).then(fileWriter=>new Promise((resolve,reject)=>{ fileWriter.onerror=reject; fileWriter.onwriteend=resolve; fileWriter.write(zip.file(zipDirectory).asArrayBuffer()); })).then(writeFile); return (fileName.length?game.createDir(`extension/${extensionName}/${fileName.join('/')}`).then(()=>letGo(`${fileName.join('/')}/${name}`)):letGo(name)); }; return writeFile(); }).catch(UHP); } else{ localStorage.setItem(`${lib.configprefix}extension_${extensionName}`,str); const hiddenFileFlags=['.','_'],fileList=Object.keys(zip.files).filter(filePath=>!hiddenFileFlags.includes(filePath[0])&&filePath[filePath.length-1]!='/'); if(fileList.length&&lib.db){ lib.config.extensionInfo[extensionName]={ file:fileList }; game.saveConfigValue('extensionInfo'); fileList.forEach(filePath=>{ const arrayBuffer=zip.file(filePath).asArrayBuffer(); if(!arrayBuffer) return; const blob=new Blob([arrayBuffer]); new Promise((resolve,reject)=>{ const fileReader=new FileReader(); fileReader.onerror=reject; fileReader.onload=resolve; fileReader.readAsDataURL(blob,'UTF-8'); }).then(fileLoadedEvent=>game.putDB('image',`extension-${extensionName}:${filePath}`,fileLoadedEvent.target.result)); }); } finishLoad(); } delete game.importedPack; } catch(error){ UHP(error); return false; } }), export:function(textToWrite,name){ var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}); var fileNameToSaveAs = name||'noname'; fileNameToSaveAs=fileNameToSaveAs.replace(/\\|\/|\:|\?|\"|\*|<|>|\|/g,'.'); if(lib.device){ var directory; if(lib.device=='android'){ directory=cordova.file.externalDataDirectory; } else{ directory=cordova.file.documentsDirectory; } window.resolveLocalFileSystemURL(directory,function(entry){ entry.getFile(fileNameToSaveAs,{create:true},function(fileEntry){ fileEntry.createWriter(function(fileWriter){ fileWriter.onwriteend=function(){ alert('文件已导出至'+directory+fileNameToSaveAs); } fileWriter.write(textFileAsBlob) }); }); }); } else{ var downloadLink = document.createElement("a"); downloadLink.download = fileNameToSaveAs; downloadLink.innerHTML = "Download File"; downloadLink.href = window.URL.createObjectURL(textFileAsBlob); downloadLink.click(); } }, multiDownload2:function(list,onsuccess,onerror,onfinish,process,dev){ list=list.slice(0); var download=function(){ if(list.length){ var current=list.shift(); var current2; if(typeof process=='function'){ current2=process(current); } else{ current2=current; } if(current.startsWith('theme')){ game.print(current.slice(6)); } else if(current.startsWith('image/skin')){ game.print(current.slice(11)); } else{ game.print(current.slice(current.lastIndexOf('/')+1)); } game.download(current,current2,function(){ if(onsuccess) onsuccess(list.length); download(); },function(){ if(onerror) onerror(list.length); download(); },dev); } else{ if(onfinish) onfinish(); } } download(); }, multiDownload:function(list,onsuccess,onerror,onfinish,process,dev){ if(lib.config.dev) game.print(get.url()); var args=Array.from(arguments); if(list.length<=3){ game.multiDownload2.apply(this,args); } else{ var num=Math.round(list.length/3); var left=3; args[3]=function(){ left--; if(left==0){ onfinish(); } }; setTimeout(function(){ args[0]=list.slice(0,num);game.multiDownload2.apply(game,args); }); setTimeout(function(){ args[0]=list.slice(num,2*num);game.multiDownload2.apply(this,args); },200); setTimeout(function(){ args[0]=list.slice(2*num);game.multiDownload2.apply(this,args); },400); } }, fetch:function(url,onload,onerror,onprogress){ var tmpName='~tmp'+get.id(); game.download(encodeURI(url),tmpName,function(){ game.readFile(tmpName,function(data){ onload(data); game.removeFile(tmpName); },onerror); },onerror,null,onprogress); }, playVideo:function(time,mode){ if(!_status.replayvideo){ localStorage.setItem(lib.configprefix+'playbackmode',lib.config.mode); } game.saveConfig('mode',mode); localStorage.setItem(lib.configprefix+'playback',time); game.reload(); }, playVideoContent:function(video){ var next=game.createEvent('video',false); next.video=video; ui.system.style.display='none'; ui.system.hide(); ui.arena.style.display='none'; ui.arena.hide(); ui.window.classList.remove('leftbar'); ui.window.classList.remove('rightbar'); ui.historybar.style.display='none'; _status.event=next; _status.paused=false; _status.paused2=false; _status.over=false; _status.video=true; clearTimeout(_status.timeout); for(var i in lib.characterPack){ for(var j in lib.characterPack[i]){ lib.character[j]=lib.character[j]||lib.characterPack[i][j]; } } next.setContent('playVideoContent'); game.loop(); }, videoContent:{ arrangeLib:function(content){ for(var i in content){ for(var j in content[i]){ lib[i][j]=content[i][j]; } } }, $syncDisable:function(player,map){ player.disabledSlots=map; player.$syncDisable(map) }, $syncExpand:function(player,map){ player.expandedSlots=map; player.$syncExpand(map) }, $disableJudge:function(player,map){ player.$disableJudge() }, $enableJudge:function(player,map){ player.$enableJudge() }, jiuNode:function(player,bool){ //Powered by 升麻 if(bool){ if(!player.node.jiu&&lib.config.jiu_effect){ player.node.jiu=ui.create.div('.playerjiu',player.node.avatar); player.node.jiu2=ui.create.div('.playerjiu',player.node.avatar2); } } else{ if(player.node.jiu){ player.node.jiu.delete(); player.node.jiu2.delete(); delete player.node.jiu; delete player.node.jiu2; } } }, init:function(players){ if(game.chess) return; if(lib.config.mode=='versus'){ players.bool=players.pop(); } ui.arena.setNumber(players.length); ui.arena.classList.add('video'); game.players.length=0; game.dead.length=0; ui.create.players(players.length); game.me=game.players[0]; ui.handcards1=game.me.node.handcards1; ui.handcards2=game.me.node.handcards2; ui.handcards1Container.appendChild(ui.handcards1); ui.handcards2Container.appendChild(ui.handcards2); if(lib.config.mode=='versus'){ if(players.bool){ ui.arena.setNumber(parseInt(ui.arena.dataset.number)+1); for(var i=0;i.card,#chess>.card'); var nodes=[]; for(var i=0;i.card,#chess>.card'); var nodes=[]; for(var i=0;i.card,#chess>.card'); var nodes=[]; for(var i=0;i=0;j--){ if(card[2]==nodes[j].name&&card[0]==nodes[j].suit&&card[1]==nodes[j].number){ nodes[j].classList.add('thrownhighlight'); break; } } } else{ console.log(player,cards); } }, uiClear:function(){ ui.clear(); }, judge1:function(player,content){ if(player&&content){ var judging=get.infoCard(content[0]); if(game.chess){ judging.copy('thrown','center','thrownhighlight',ui.arena).animate('start'); } else{ player.$throwordered(judging.copy('thrownhighlight'),true); } ui.create.dialog(content[1]).videoId=content[2]; ui.arena.classList.add('thrownhighlight'); } else{ console.log(player); } }, centernode:function(content){ get.infoCard(content).copy('thrown','center','thrownhighlight',ui.arena).animate('start'); }, judge2:function(videoId){ for(var i=0;i1){ player.node.marks.lastChild.remove(); } player.classList.add('dead'); player.classList.remove('turnedover'); player.classList.remove('out'); player.node.count.innerHTML='0'; player.node.hp.hide(); player.node.equips.hide(); player.node.count.hide(); player.previous.next=player.next; player.next.previous=player.previous; game.players.remove(player); game.dead.push(player); if(lib.config.mode=='stone'){ setTimeout(function(){ player.delete(); },500); } }, tafangMe:function(player){ if(player){ game.me=player; ui.me.lastChild.show(); ui.create.fakeme(); ui.handcards1=player.node.handcards1.animate('start').fix(); ui.handcards2=player.node.handcards2.animate('start').fix(); ui.handcards1Container.appendChild(ui.handcards1); ui.handcards2Container.appendChild(ui.handcards2); ui.updatehl(); game.setChessInfo(); } }, deleteChessPlayer:function(player){ if(player){ player.delete(); delete game.playerMap[player.dataset.position]; game.players.remove(player); for(var i=0;i{ lib.status.reload--; if(lib.status.reload==0&&lib.ondb2.length){ const command=lib.ondb2.shift(); game[command[0]](...command[1]); } if(lib.status.reload==0&&lib.ondb.length){ const command=lib.ondb.shift(); game[command[0]](...command[1]); } if(lib.status.reload||!_status.waitingToReload) return; window.location.reload(); delete _status.waitingToReload; }, exit:function(){ var ua=userAgent; var ios=ua.includes('iphone')||ua.includes('ipad')||ua.includes('macintosh'); //electron if(typeof window.process=='object'&&typeof window.require=='function'){ var versions=window.process.versions; var electronVersion=parseFloat(versions.electron); var remote; if(electronVersion>=14){ remote=require('@electron/remote'); }else{ remote=require('electron').remote; } var thisWindow=remote.getCurrentWindow(); thisWindow.destroy(); window.process.exit(); } // android-cordova环境 else if(lib.device==='android'){ if(navigator.app&&navigator.app.exitApp){ navigator.app.exitApp(); } } //ios-cordova环境或ios浏览器环境 else if(lib.device==='ios'||!lib.device&&ios){ game.saveConfig('mode'); if(_status){ if(_status.reloading)return; _status.reloading=true; } if(_status.video&&!_status.replayvideo) { localStorage.removeItem(lib.configprefix+'playbackmode'); } window.location.reload(); } //非ios的网页版 else if(!ios){ window.onbeforeunload = null; window.close(); } }, open:function(url){ if(lib.device){ if(cordova.InAppBrowser){ cordova.InAppBrowser.open(url,'_system'); } else{ ui.create.iframe(url); } } else{ window.open(url); } }, reloadCurrent:function(){ game.saveConfig('continue_name',[game.me.name1||game.me.name,game.me.name2]); game.saveConfig('mode',lib.config.mode); localStorage.setItem(lib.configprefix+'directstart',true); game.reload(); }, update:function(func){ lib.updates.push(func); if(lib.updates.length===1){ game.run(); } return func; }, unupdate:function(func){ lib.updates.remove(func); }, stop:function(){ cancelAnimationFrame(lib.status.frameId); }, run:function(){ if(lib.updates.length){ cancelAnimationFrame(lib.status.frameId); lib.status.frameId=requestAnimationFrame(function(time){ if(lib.status.time!==0){ lib.status.delayed+=time-lib.status.time; } lib.status.frameId=requestAnimationFrame(lib.run); }); } }, addVideo:function(type,player,content){ if(_status.video||game.online) return; if(!_status.videoInited){ if(type=='arrangeLib'){ lib.video.push({ type:type, player:player, content:content, delay:0 }); } return; } if(type=='storage'&&player&&player.updateMarks){ player.updateMarks(); } if(game.getVideoName){ var time=get.time(); if(!_status.lastVideoLog){ _status.lastVideoLog=time; } if(get.itemtype(player)=='player'){ player=player.dataset.position; } lib.video.push({ type:type, player:player, content:content, delay:time-_status.lastVideoLog }); _status.lastVideoLog=time; } }, draw:function(func){ lib.canvasUpdates.push(func); if(!lib.status.canvas){ lib.status.canvas=true; game.update(lib.updateCanvas); } }, vibrate:function(time){ if(typeof navigator.vibrate=='function'){ navigator.vibrate(time||500); } }, prompt:function(){ var str,forced,callback,noinput=false,str2=''; for(var i=0;ix){ this.speed.x=Math.abs(this.speed.x); } this.life*=1.3; this.death*=1.3; break; } case 'dust':{ this.r = Math.round(Math.random()*55)+105; this.g = Math.round(Math.random()*55)+150; this.b = 255; this.location.x+=Math.round(Math.random()*60)-30; this.location.y+=Math.round(Math.random()*40)-20; if(this.location.xx){ this.speed.x=Math.abs(this.speed.x); } this.life*=1.3; this.death*=1.3; break; } case 'legend':{ this.r = 255; this.g = Math.round(Math.random()*100+155); this.b = Math.round(Math.random()*100+50); this.location.x+=Math.round(Math.random()*60)-30; this.location.y+=Math.round(Math.random()*40)-20; if(this.location.xx){ this.speed.x=Math.abs(this.speed.x); } this.speed.x/=2; this.speed.y/=2; this.life*=2; this.death*=2; break; } case 'epic':{ this.r = Math.round(Math.random()*55)+200; this.g = Math.round(Math.random()*100)+55; this.b = 255; this.location.x+=Math.round(Math.random()*60)-30; this.location.y+=Math.round(Math.random()*40)-20; if(this.location.xx){ this.speed.x=Math.abs(this.speed.x); } this.speed.x/=2; this.speed.y/=2; this.life*=2; this.death*=2; break; } case 'rare':{ this.r = Math.round(Math.random()*55)+105; this.g = Math.round(Math.random()*55)+150; this.b = 255; this.location.x+=Math.round(Math.random()*60)-30; this.location.y+=Math.round(Math.random()*40)-20; if(this.location.xx){ this.speed.x=Math.abs(this.speed.x); } this.speed.x/=2; this.speed.y/=2; this.life*=2; this.death*=2; break; } case 'recover':{ this.g = 255; this.r = Math.round(Math.random()*200+55); this.b = Math.round(Math.random()*155+55); this.location.x+=Math.round(Math.random()*60)-30; this.location.y+=Math.round(Math.random()*40)-20; if(this.location.xx){ this.speed.x=Math.abs(this.speed.x); } this.speed.x/=2; this.speed.y/=2; this.life*=2; this.death*=2; break; } default:{ this.r = 255; this.g = Math.round(Math.random()*155); this.b = 0; } } } game.draw(function(time,surface){ surface.globalCompositeOperation = "source-over"; surface.globalCompositeOperation = "lighter"; for(var i = 0; i < particles.length; i++) { var p = particles[i]; surface.beginPath(); var middle=0.5; var radius=p.radius; if(type=='recover'||type=='legend'||type=='rare'|| type=='epic'||type=='coin'||type=='dust'){ middle=0.7; radius/=3; } p.opacity = Math.round(p.death/p.life*100)/100 var gradient = surface.createRadialGradient(p.location.x, p.location.y, 0, p.location.x, p.location.y, p.radius); gradient.addColorStop(0, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")"); gradient.addColorStop(middle, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")"); gradient.addColorStop(1, "rgba("+p.r+", "+p.g+", "+p.b+", 0)"); surface.fillStyle = gradient; surface.arc(p.location.x, p.location.y, radius, Math.PI*2, false); surface.fill(); p.death--; if(type=='recover'){ p.radius+=0.5; } else if(type=='coin'||type=='dust'){ p.radius+=0.7; } else if(type=='legend'||type=='rare'||type=='epic'){ p.radius+=0.5; } else { p.radius++; } p.location.x += (p.speed.x); p.location.y += (p.speed.y); if(p.death < 0 || p.radius < 0){ if(typeof duration=='number'&&time+500>=duration){ particles.splice(i--,1); } else{ particles[i] = new particle(); } } } if(particles.length==0){ return false; } }); } }, linexy:function(path){ const from=[path[0],path[1]],to=[path[2],path[3]]; let total=typeof arguments[1]==='number'?arguments[1]:lib.config.duration*2,opacity=1,color=[255,255,255],dashed=false,drag=false; if(arguments[1]&&typeof arguments[1]=='object') Object.keys(arguments[1]).forEach(value=>{ switch(value){ case 'opacity': opacity=arguments[1][value]; break; case 'color': color=arguments[1][value]; break; case 'dashed': dashed=arguments[1][value]; break; case 'duration':total=arguments[1][value]; } }); else if(typeof arguments[1]=='string') color=arguments[1]; if(typeof color=='string') color=lib.lineColor.get(color)||[255,255,255]; let node; if(arguments[1]=='drag'){ color=[236,201,71]; drag=true; if(arguments[2]) node=arguments[2]; else{ node=ui.create.div('.linexy.drag'); node.style.left=`${from[0]}px`; node.style.top=`${from[1]}px`; node.style.background=`linear-gradient(transparent,rgba(${color.toString()},${opacity}),rgba(${color.toString()},${opacity}))`; if(game.chess) ui.chess.appendChild(node); else ui.arena.appendChild(node); } } else{ node=ui.create.div('.linexy.hidden'); node.style.left=`${from[0]}px`; node.style.top=`${from[1]}px`; node.style.background=`linear-gradient(transparent,rgba(${color.toString()},${opacity}),rgba(${color.toString()},${opacity}))`; node.style.transitionDuration=`${total/3000}s`; } const dy=to[1]-from[1],dx=to[0]-from[0]; let deg=Math.atan(Math.abs(dy)/Math.abs(dx))/Math.PI*180; if(dx>=0) if(dy<=0) deg+=90; else deg=90-deg; else if(dy<=0) deg=270-deg; else deg+=270; if(drag){ node.style.transform=`rotate(${(-deg)}deg)`; node.style.height=`${get.xyDistance(from,to)}px`; } else{ node.style.transform=`rotate(${(-deg)}deg) scaleY(0)`; node.style.height=`${get.xyDistance(from,to)}px`; if(get.objtype(arguments[1])=='div') arguments[1].appendChild(node); else if(game.chess) ui.chess.appendChild(node); else ui.arena.appendChild(node); ui.refresh(node); node.show(); node.style.transform=`rotate(${(-deg)}deg) scaleY(1)`; node.listenTransition(()=>setTimeout(()=>{ if(!node.classList.contains('removing')) node.delete(); },total/3)); } return node; }, _linexy:function(path){ var from=[path[0],path[1]]; var to=[path[2],path[3]]; var total=typeof arguments[1]==='number'?arguments[1]:lib.config.duration*2; var opacity=1; var color=[255,255,255]; var dashed=false; if(typeof arguments[1]=='object'){ for(var i in arguments[1]){ switch(i){ case 'opacity':opacity=arguments[1][i];break; case 'color':color=arguments[1][i];break; case 'dashed':dashed=arguments[1][i];break; case 'duration':total=arguments[1][i];break; } } } else if(arguments[1]=='fire'||arguments[1]=='thunder'||arguments[1]=='green'){ color=arguments[1]; } if(color=='fire'){ color=[255, 146, 68]; } else if(color=='thunder'){ color=[141, 216, 255]; } else if(color=='green'){ color=[141, 255, 216]; } var drawfunc=function(time,ctx){ var current; if(timetotal/1.5){ ctx.strokeStyle='rgba('+color.toString()+','+opacity*(1-(time-total/1.5)/(total-total/1.5))+')'; } else{ ctx.strokeStyle='rgba('+color.toString()+','+opacity+')'; } } else{ return false; } ctx.beginPath(); if(dashed){ ctx.lineCap='butt'; ctx.setLineDash([8,2]); } else{ ctx.lineCap='round'; } ctx.moveTo(from[0],from[1]); ctx.lineTo(current[0],current[1]); ctx.stroke(); }; if(arguments[2]&&game.chess){ game.draw2(drawfunc); } else{ game.draw(drawfunc); } }, createTrigger:function(name,skill,player,event){ var info=get.info(skill); if(!info) return false; if((player.isOut()||player.removed)&&!info.forceOut) return; if(player.isDead()&&!info.forceDie) return; var next=game.createEvent('trigger',false); next.skill=skill; next.player=player; next.triggername=name; next.forceDie=true; next.includeOut=true; next._trigger=event; next.setContent('createTrigger'); }, /** * @legacy Use {@link lib.element.GameEvent.constructor} instead. */ createEvent:(name,trigger,triggerEvent)=>{ const next=new lib.element.GameEvent(name,trigger); (triggerEvent||_status.event).next.push(next); return next; }, addCharacter:(name,information)=>{ const extensionName=_status.extension||information.extension,character=[ information.sex, information.group, information.hp, information.skills||[], [ _status.evaluatingExtension?`db:extension-${extensionName}:${name}.jpg`:`ext:${extensionName}/${name}.jpg`, `die:ext:${extensionName}/${name}.mp3` ] ]; if(information.tags) character[4]=character[4].concat(information.tags); lib.character[name]=character; const packName=`mode_extension_${extensionName}`; if(!lib.characterPack[packName]) lib.characterPack[packName]={}; lib.translate[name]=information.translate; lib.characterPack[packName][name]=character; lib.translate[`${packName}_character_config`]=extensionName; }, addCharacterPack:(pack,packagename)=>{ var extname=_status.extension||'扩展'; let gzFlag=false; packagename=packagename||extname; for(var i in pack){ if(i=='mode'){ if(pack[i]=="guozhan") gzFlag=true; continue; } if(i=='forbid') continue; for(var j in pack[i]){ if(i=='character'){ if(!pack[i][j][4]){ pack[i][j][4]=[]; } var imgsrc; if(_status.evaluatingExtension){ imgsrc='db:extension-'+extname+':'+j+'.jpg'; } else{ imgsrc='ext:'+extname+'/'+j+'.jpg'; } const audiosrc='die:ext:'+extname+'/'+j+'.mp3'; if(!pack[i][j][4].some(str=>typeof str=="string"&&/^(?:db:extension-|ext:):(?:.+)/.test(str))) pack[i][j][4].add(imgsrc); if(!pack[i][j][4].some(str=>typeof str=="string"&&/^die:(?:.+)/.test(str))) pack[i][j][4].add(audiosrc); if(pack[i][j][4].contains('boss')|| pack[i][j][4].contains('hiddenboss')){ lib.config.forbidai.add(j); } if(lib.config.forbidai_user&&lib.config.forbidai_user.contains(j)){ lib.config.forbidai.add(j); } for(var l=0;l{ const prefix=`extension_${extensionName}`; Object.keys(lib.config).forEach(key=>{ if(key.startsWith(prefix)) game.saveConfig(key); }); localStorage.removeItem(`${lib.configprefix}${prefix}`); game.deleteDB('data',prefix); lib.config.extensions.remove(extensionName); game.saveConfig('extensions',lib.config.extensions); const modeList=lib.config.extensionInfo[extensionName]; if(modeList){ if(modeList.file) Object.values(modeList.file).forEach(filePath=>game.deleteDB('image',`extension-${extensionName}:${filePath}`)); if(modeList.mode) Object.values(modeList.mode).forEach(game.clearModeConfig); delete lib.config.extensionInfo[extensionName]; game.saveConfigValue('extensionInfo'); } if(!game.download||keepFile) return; if(lib.node&&lib.node.fs) try{ const deleteFolderRecursive=path=>{ if(!lib.node.fs.existsSync(path)) return; lib.node.fs.readdirSync(path).forEach((file,index)=>{ const currentPath = `${path}/${file}`; if (lib.node.fs.lstatSync(currentPath).isDirectory()) deleteFolderRecursive(currentPath); else lib.node.fs.unlinkSync(currentPath); }); lib.node.fs.rmdirSync(path); }; deleteFolderRecursive(`${__dirname}/extension/${extensionName}`); } catch(error){ console.log(error); } else new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(`${lib.assetURL}extension/${extensionName}`,resolve,reject)).then(directoryEntry=>directoryEntry.removeRecursively()); }, addRecentCharacter:function(){ var list=get.config('recentCharacter')||[]; for(var i=0;inum){ list.splice(num); } game.saveConfig('recentCharacter',list,true); }, createCard:function(name,suit,number,nature){ if(typeof name=='object'){ nature=name.nature; number=name.number; suit=name.suit; name=name.name; } if(typeof name!='string'){ name='sha'; } var noclick=false; if(suit=='noclick'){ noclick=true; suit=null; } if(!suit&&lib.card[name].cardcolor){ suit=lib.card[name].cardcolor; } if(!nature&&lib.card[name].cardnature){ nature=lib.card[name].cardnature; } if(typeof suit!='string'){ suit=['heart','diamond','club','spade'].randomGet(); } else if(suit=='black'){ suit=Math.random()<0.5?'club':'spade'; } else if(suit=='red'){ suit=Math.random()<0.5?'diamond':'heart'; } if(typeof number!='number'&&typeof number!='string'){ number=Math.ceil(Math.random()*13); } var card; if(noclick){ card=ui.create.card(ui.special,'noclick',true); } else{ card=ui.create.card(ui.special); } card.storage.vanish=true; return card.init([suit,number,name,nature]); }, createCard2:function(){ var card=game.createCard.apply(this,arguments); delete card.storage.vanish; return card; }, forceOver:function(bool,callback){ _status.event.next.length=0; var next=game.createEvent('finish_game'); next.bool=bool; next.callback=callback; next.setContent('forceOver'); if(_status.paused){ game.uncheck(); game.resume(); } }, over:function(result){ if(_status.over) return; if(game.me._trueMe) game.swapPlayer(game.me._trueMe); var i,j,k,num,table,tr,td,dialog; _status.over=true; ui.control.show(); ui.clear(); game.stopCountChoose(); if(ui.time3){ clearInterval(ui.time3.interval); } if((game.layout=='long2'||game.layout=='nova')&&!game.chess){ ui.arena.classList.add('choose-character'); ui.me.hide(); ui.mebg.hide() ui.autonode.hide(); if(lib.config.radius_size!='off'){ ui.historybar.style.borderRadius='0 0 0 4px'; } } if(game.online){ var dialog=ui.create.dialog(); dialog.noforcebutton=true; dialog.content.innerHTML=result; dialog.forcebutton=true; var result2=arguments[1]; if(result2==true){ dialog.content.firstChild.innerHTML='战斗胜利'; } else if(result2==false){ dialog.content.firstChild.innerHTML='战斗失败'; } ui.update(); dialog.add(ui.create.div('.placeholder')); for(var i=0;i'+get.translation(game.players[i])+''); dialog.addSmall(hs); } } for(var j=0;j'+get.translation(game.dead[j])+''); dialog.addSmall(hs); } } dialog.add(ui.create.div('.placeholder.slim')); if(lib.config.background_audio){ if(result2===true){ game.playAudio('effect','win'); } else if(result2===false){ game.playAudio('effect','lose'); } else{ game.playAudio('effect','tie'); } } if(!ui.exit){ ui.create.exit(); } if(ui.giveup){ ui.giveup.remove(); delete ui.giveup; } if(game.servermode){ ui.exit.firstChild.innerHTML='返回房间'; setTimeout(function(){ ui.exit.firstChild.innerHTML='退出房间'; _status.roomtimeout=true; lib.config.reconnect_info[2]=null; game.saveConfig('reconnect_info',lib.config.reconnect_info); },10000); } if(ui.tempnowuxie){ ui.tempnowuxie.close(); delete ui.tempnowuxie; } if(ui.auto) ui.auto.hide(); if(ui.wuxie) ui.wuxie.hide(); if(game.getIdentityList){ for(var i=0;i40){ mmr=40; } else if(mmr<10){ mmr=10; } dialog.add(ui.create.div('','获得 '+mmr+' 积分')); } else{ mmr=-30+Math.round(mmr/2); if(mmr>-20){ mmr=-20; } else if(mmr<-35){ mmr=-35; } if(lib.storage.ladder.current<900){ mmr=Math.round(mmr/4); } else if(lib.storage.ladder.current<1400){ mmr=Math.round(mmr/2); } else if(lib.storage.ladder.current<2000){ mmr=Math.round(mmr/1.5); } else if(lib.storage.ladder.current>2500){ mmr=Math.round(mmr*1.5); } dialog.add(ui.create.div('','失去 '+(-mmr)+' 积分')); } if(_status.ladder_tmp){ lib.storage.ladder.current+=40; delete _status.ladder_tmp; } lib.storage.ladder.current+=mmr; if(lib.storage.ladder.top'+get.translation(game.players[i])+''); dialog.addSmall(hs); } } for(var i=0;i'+get.translation(game.dead[i])+''); dialog.addSmall(hs); } } dialog.add(ui.create.div('.placeholder.slim')); game.addVideo('over',null,dialog.content.innerHTML); var vinum=parseInt(lib.config.video); if(!_status.video&&vinum&&game.getVideoName&&window.indexedDB&&_status.videoInited){ var store=lib.db.transaction(['video'],'readwrite').objectStore('video'); var videos=lib.videos.slice(0); for(var i=0;i=vinum){ var toremove=videos.pop(); lib.videos.remove(toremove); store.delete(toremove.time); } else{ break; } } var me=game.me||game.players[0]; if(!me) return; var newvid={ name:game.getVideoName(), mode:lib.config.mode, video:lib.video, win:result=='战斗胜利', name1:me.name1||me.name, name2:me.name2, time:lib.getUTC(new Date()) }; var modecharacters=lib.characterPack['mode_'+get.mode()]; if(modecharacters){ if(get.mode()=='guozhan'){ if(modecharacters[newvid.name1]){ if(newvid.name1.startsWith('gz_shibing')){ newvid.name1=newvid.name1.slice(3,11); } else{ newvid.name1=newvid.name1.slice(3); } } if(modecharacters[newvid.name2]){ if(newvid.name2.startsWith('gz_shibing')){ newvid.name2=newvid.name2.slice(3,11); } else{ newvid.name2=newvid.name2.slice(3); } } } else{ if(modecharacters[newvid.name1]){ newvid.name1=get.mode()+'::'+newvid.name1; } if(modecharacters[newvid.name2]){ newvid.name2=get.mode()+'::'+newvid.name2; } } } if(newvid.name1&&newvid.name1.startsWith('subplayer_')){ newvid.name1=newvid.name1.slice(10,newvid.name1.lastIndexOf('_')); } if(newvid.name2&&newvid.name2.startsWith('subplayer_')){ newvid.name1=newvid.name2.slice(10,newvid.name1.lastIndexOf('_')); } lib.videos.unshift(newvid); store.put(newvid); ui.create.videoNode(newvid,true); } // _status.auto=false; if(ui.auto){ // ui.auto.classList.remove('glow'); ui.auto.hide(); } if(ui.wuxie) ui.wuxie.hide(); if(ui.giveup){ ui.giveup.remove(); delete ui.giveup; } if(lib.config.test_game&&!_status.connectMode){ if(typeof lib.config.test_game!=='string'){ switch(lib.config.mode){ case 'identity':game.saveConfig('mode','guozhan');break; case 'guozhan':game.saveConfig('mode','versus');break; case 'versus':game.saveConfig('mode','boss');break; case 'boss':game.saveConfig('mode','chess');break; case 'chess':game.saveConfig('mode','stone');break; case 'stone':game.saveConfig('mode','identity');break; } } setTimeout(game.reload,500); } if(game.controlOver){ game.controlOver();return; } if(!_status.brawl){ if(lib.config.mode=='boss'){ ui.create.control('再战',function(){ var pointer=game.boss; var map={boss:game.me==game.boss,links:[]}; for(var iwhile=0;iwhile<10;iwhile++){ pointer=pointer.nextSeat; if(pointer==game.boss){ break; } if(!pointer.side){ map.links.push(pointer.name); } } game.saveConfig('continue_name_boss',map); game.saveConfig('mode',lib.config.mode); localStorage.setItem(lib.configprefix+'directstart',true); game.reload(); }); } else if(lib.config.mode=='versus'){ if(_status.mode=='standard'||_status.mode=='three'){ ui.create.control('再战',function(){ game.saveConfig('continue_name_versus'+(_status.mode=='three'?'_three':''),{ friend:_status.friendBackup, enemy:_status.enemyBackup, color:_status.color }); game.saveConfig('mode',lib.config.mode); localStorage.setItem(lib.configprefix+'directstart',true); game.reload(); }); } } else if(!_status.connectMode&&get.config('continue_game')&&!ui.continue_game&&!_status.brawl&&!game.no_continue_game){ ui.continue_game=ui.create.control('再战',game.reloadCurrent); } } if(!ui.restart){ if(game.onlineroom&&typeof game.roomId=='string'){ ui.restart=ui.create.control('restart',function(){ game.broadcastAll(function(){ if(ui.exit){ ui.exit.stay=true; ui.exit.firstChild.innerHTML='返回房间'; } }); game.saveConfig('tmp_owner_roomId',game.roomId); setTimeout(game.reload,100); }); } else{ ui.restart=ui.create.control('restart',game.reload); } } if(ui.tempnowuxie){ ui.tempnowuxie.close(); delete ui.tempnowuxie; } if(ui.revive){ ui.revive.close(); delete ui.revive; } if(ui.swap){ ui.swap.close(); delete ui.swap; } for(var i=0;i0){ var next=event.next.shift(); if(next.player&&next.player.skipList.contains(next.name)){ event.trigger(next.name+'Skipped'); next.player.skipList.remove(next.name); if(lib.phaseName.contains(next.name)) next.player.getHistory('skipped').add(next.name); } else{ next.parent=event; _status.event=next; game.getGlobalHistory('everything').push(next); } } else if(event.finished){ if(event._triggered==1){ if(event.type=='card') event.trigger('useCardToOmitted'); event.trigger(event.name+'Omitted'); event._triggered=4; } else if(event._triggered==2){ if(event.type=='card') event.trigger('useCardToEnd'); event.trigger(event.name+'End'); event._triggered=3; } else if(event._triggered==3){ if(event.type=='card') event.trigger('useCardToAfter'); event.trigger(event.name+'After'); event._triggered++; } else if(event.after&&event.after.length){ var next=event.after.shift(); if(next.player&&next.player.skipList.contains(next.name)){ event.trigger(next.name+'Skipped'); next.player.skipList.remove(next.name); if(lib.phaseName.contains(next.name)) next.player.getHistory('skipped').add(next.name) } else{ next.parent=event; _status.event=next; } } else{ if(event.parent){ if(event.result){ event.parent._result=event.result; } _status.event=event.parent; } else{ return; } } } else{ if(event._triggered==0){ if(event.type=='card') event.trigger('useCardToBefore'); event.trigger(event.name+'Before'); event._triggered++; } else if(event._triggered==1){ if(event.type=='card') event.trigger('useCardToBegin'); event.trigger(event.name+'Begin'); event._triggered++; /*if(event.name=='phase'&&!event._begun){ var next=game.createEvent('phasing',false,event); next.player=event.player; next.skill=event.skill; next.setContent('phasing'); event._begun=true; } else{ event.trigger(event.name+'Begin'); event._triggered++; }*/ } else{ event.callHandler(); if(player&&player.classList.contains('dead')&&!event.forceDie&&event.name!='phaseLoop'){ game.broadcastAll(function(){ while(_status.dieClose.length){ _status.dieClose.shift().close(); } }); if(event._oncancel){ event._oncancel(); } event.finish(); } else if(player&&player.removed&&event.name!='phaseLoop'){ event.finish(); } else if(player&&player.isOut()&&event.name!='phaseLoop'&&!event.includeOut){ if(event.name=='phase'&&player==_status.roundStart&&!event.skill){ _status.roundSkipped=true; } event.finish(); } else{ if(_status.withError||lib.config.compatiblemode||(_status.connectMode&&!lib.config.debug)){ try{ if(event.content instanceof GeneratorFunction){ if(!event.debugging){ if(event.generatorContent) event.generatorContent.return(); event.generatorContent=event.content(event,step,source,player,target,targets, card,cards,skill,forced,num,trigger,result, _status,lib,game,ui,get,ai); }else{ delete event.debugging; } var next=event.generatorContent.next(); if(typeof next.value=='function'&&next.value.toString()=='code=>eval(code)'){ //触发debugger var inputCallback=inputResult=>{ if(inputResult===false){ event.debugging=true; game.resume2(); }else{ alert(get.stringify(next.value(inputResult))); game.prompt('','debugger调试',inputCallback); } } game.prompt('','debugger调试',inputCallback); return game.pause2(); } if(event.finished) event.generatorContent.return(); }else{ event.content(event,step,source,player,target,targets, card,cards,skill,forced,num,trigger,result, _status,lib,game,ui,get,ai); } } catch(e){ game.print('游戏出错:'+event.name); game.print(e.toString()); console.log(e); } } else{ if(event.content instanceof GeneratorFunction){ if(!event.debugging){ if(event.generatorContent) event.generatorContent.return(); event.generatorContent=event.content(event,step,source,player,target,targets, card,cards,skill,forced,num,trigger,result, _status,lib,game,ui,get,ai); }else{ delete event.debugging; } var next=event.generatorContent.next(); if(typeof next.value=='function'&&next.value.toString()=='code=>eval(code)'){ //触发debugger var inputCallback=inputResult=>{ if(inputResult===false){ event.debugging=true; game.resume2(); }else{ alert(get.stringify(next.value(inputResult))); game.prompt('','debugger调试',inputCallback); } } game.prompt('','debugger调试',inputCallback); return game.pause2(); } if(event.finished) event.generatorContent.return(); }else{ event.content(event,step,source,player,target,targets, card,cards,skill,forced,num,trigger,result, _status,lib,game,ui,get,ai); } } } event.clearStepCache(); event.step++; if(event.finished) event.callHandler(); } } } }, pause:function(){ clearTimeout(_status.timeout); _status.paused=true; }, pause2:function(){ if(_status.connectMode) return; _status.paused2=true; }, resume:function(){ if(_status.paused){ if(!_status.noclearcountdown){ game.stopCountChoose(); } _status.paused=false; delete _status.waitingForTransition; game.loop(); } }, resume2:function(){ if(_status.connectMode) return; if(_status.paused2){ _status.paused2=false; game.loop(); } }, delaye:function(){ var next=game.createEvent('delay',false); next.setContent('delay'); next._args=Array.from(arguments); return next; }, delayex:function(){ var next=game.createEvent('delayx',false); next.setContent('delay'); next._args=Array.from(arguments); return next; }, delay:function(time,time2){ if(_status.paused) return; game.pause(); if(typeof time!='number') time=1; if(typeof time2!='number') time2=0; time=time*lib.config.duration+time2; if(lib.config.speed=='vvfast') time/=3; _status.timeout=setTimeout(game.resume,time); }, delayx:function(time,time2){ if(typeof time!='number') time=1; switch(lib.config.game_speed){ case 'vslow':time*=2.5;break; case 'slow':time*=1.5;break; case 'fast':time*=0.7;break; case 'vfast':time*=0.4;break; case 'vvfast':time*=0.2;break; } return game.delay(time,time2); }, check:function(event){ var i,j,range; if(event==undefined) event=_status.event; event._checked=true; var custom=event.custom||{}; var ok=true,auto=true; var player=event.player; var auto_confirm=lib.config.auto_confirm; var players=game.players.slice(0); if(event.deadTarget) players.addArray(game.dead); if(!event.filterButton&&!event.filterCard&&!event.filterTarget&&(!event.skill||!event._backup)){ if(event.choosing){ _status.imchoosing=true; } return; } player.node.equips.classList.remove('popequip'); if(event.filterButton){ var dialog=event.dialog; range=get.select(event.selectButton); var selectableButtons=false; if(event.forceAuto&&ui.selected.buttons.length==range[1]) auto=true; else if(range[0]!=range[1]||range[0]>1) auto=false; for(i=0;i-1&&!lib.config.compatiblemode){ event._cardChoice=[]; firstCheck=true; } if(event.isMine()&&event.name=='chooseToUse'&&event.parent.name=='phaseUse'&&!event.skill&& !event._targetChoice&&!firstCheck&&window.Map&&!lib.config.compatiblemode){ event._targetChoice=new Map(); for(var i=0;i1) auto=false; for(i=0;i1) auto=false; for(i=0;i7){ nochess=false; } else if(players[i].isOut()){ nochess=false; } else if(event._targetChoice&&event._targetChoice.has(card)){ var targetChoice=event._targetChoice.get(card); if(!Array.isArray(targetChoice)||!targetChoice.contains(players[i])){ nochess=false; } } else if(!event.filterTarget(card,player,players[i])){ nochess=false; } if(nochess){ if(ui.selected.targets.length=info.usable) enable=false; if(info.chooseButton&&_status.event.noButton) enable=false; if(info.round&&(info.round-(game.roundNumber-player.storage[skills2[i]+'_roundcount'])>0)) enable=false; } if(enable){ if(event.isMine()||!event._aiexclude.contains(skills2[i])){ skills.add(skills2[i]); } event._skillChoice.add(skills2[i]); } } } var globalskills=[]; var globallist=lib.skill.global.slice(0); game.expandSkills(globallist); for(var i=0;i7){ players[i].node.action.classList.add('thunder'); } else{ players[i].node.action.classList.remove('thunder'); } } } } if(ok&&(!event.filterOk||event.filterOk())&&auto&&(auto_confirm||(skillinfo&&skillinfo.direct))&&(!_status.mousedragging||!_status.mouseleft)&& !_status.mousedown&&!_status.touchnocheck){ if(ui.confirm){ if(!skillinfo||!skillinfo.preservecancel){ ui.confirm.close(); } } if(skillinfo&&skillinfo.preservecancel&&!ui.confirm){ ui.create.confirm('c'); } if(event.skillDialog==true) event.skillDialog=false; ui.click.ok(); _status.mousedragging=null; } else{ ui.arena.classList.add('selecting'); if(event.filterTarget&&(!event.filterCard||!event.position||(typeof event.position=='string'&&event.position.indexOf('e')==-1))){ ui.arena.classList.add('tempnoe'); } game.countChoose(); if(!_status.noconfirm&&!_status.event.noconfirm){ if(!_status.mousedown||_status.mouseleft){ var str=''; if(ok&&(!event.filterOk||event.filterOk())) str+='o'; if(!event.forced&&!event.fakeforce&&get.noSelected()) str+='c'; ui.create.confirm(str); } } } if(ui.confirm&&ui.confirm.lastChild.link=='cancel'){ if(_status.event.type=='phase'&&!_status.event.skill){ ui.confirm.lastChild.innerHTML='结束'; } else{ ui.confirm.lastChild.innerHTML='取消'; } } } return ok; }, uncheck:function(){ var i,j; if(game.chess){ var shadows=ui.chessContainer.getElementsByClassName('playergrid temp'); while(shadows.length){ shadows[0].remove(); } } var argc=arguments.length; var args=new Array(argc); for(var i=0;i=position){ return players[i]; } } return players[0]; }, loadModeAsync:function(name,callback){ window.game=game; var script=lib.init.js(lib.assetURL+'mode',name,gnc.of(function*(){ yield Promise.allSettled(_status.importing.mode); if(!lib.config.dev) delete window.game; script.remove(); var content=lib.imported.mode[name]; delete lib.imported.mode[name]; if(get.is.empty(lib.imported.mode)){ delete lib.imported.mode; } callback(content); })); }, switchMode:function(name,configx){ if(!lib.layoutfixed.contains(name)){ if(lib.config.layout!=game.layout){ lib.init.layout(lib.config.layout); } else if(lib.config.mode=='brawl'){ if(lib.config.player_border=='normal'&&(game.layout=='long'||game.layout=='long2')){ ui.arena.classList.add('lslim_player'); } } } window.game=game; var script=lib.init.js(lib.assetURL+'mode',name,gnc.of(function*(){ yield Promise.allSettled(_status.importing.mode); if(!lib.config.dev) delete window.game; script.remove(); var mode=lib.imported.mode; _status.sourcemode=lib.config.mode; lib.config.mode=name; var i,j,k; for(i in mode[lib.config.mode].element){ if(!lib.element[i]) lib.element[i]=[]; for(j in mode[lib.config.mode].element[i]){ if(j=='init'){ if(!lib.element[i].inits) lib.element[i].inits=[]; lib.element[i].inits.push(mode[lib.config.mode].element[i][j]); } else{ lib.element[i][j]=mode[lib.config.mode].element[i][j]; } } } for(i in mode[lib.config.mode].ai){ if(typeof mode[lib.config.mode].ai[i]=='object'){ if(ai[i]==undefined) ai[i]={}; for(j in mode[lib.config.mode].ai[i]){ ai[i][j]=mode[lib.config.mode].ai[i][j]; } } else{ ai[i]=mode[lib.config.mode].ai[i]; } } for(i in mode[lib.config.mode].ui){ if(typeof mode[lib.config.mode].ui[i]=='object'){ if(ui[i]==undefined) ui[i]={}; for(j in mode[lib.config.mode].ui[i]){ ui[i][j]=mode[lib.config.mode].ui[i][j]; } } else{ ui[i]=mode[lib.config.mode].ui[i]; } } for(i in mode[lib.config.mode].game){ game[i]=mode[lib.config.mode].game[i]; } for(i in mode[lib.config.mode].get){ get[i]=mode[lib.config.mode].get[i]; } if(game.onwash){ lib.onwash.push(game.onwash); delete game.onwash; } if(game.onover){ lib.onover.push(game.onover); delete game.onover; } lib.config.banned=lib.config[lib.config.mode+'_banned']||[]; lib.config.bannedcards=lib.config[lib.config.mode+'_bannedcards']||[]; for(i in mode[lib.config.mode]){ if(i=='element') continue; if(i=='game') continue; if(i=='ai') continue; if(i=='ui') continue; if(i=='get') continue; if(i=='config') continue; if(i=='start') continue; if(i=='startBefore') continue; if(lib[i]==undefined) lib[i]=(Array.isArray(mode[lib.config.mode][i]))?[]:{}; for(j in mode[lib.config.mode][i]){ lib[i][j]=mode[lib.config.mode][i][j]; } } // var pilecfg=lib.config.customcardpile[get.config('cardpilename')]; // if(pilecfg){ // lib.config.bannedpile=pilecfg[0]||{}; // lib.config.addedpile=pilecfg[1]||{}; // } _status.event=lib.element.GameEvent.initialGameEvent(); _status.paused=false; if(_status.connectMode&&lib.mode[name].connect){ game.saveConfig('connect_mode',name); game.clearConnect(); lib.configOL.mode=name; if(configx){ for(var i in configx){ lib.configOL[i]=configx[i]; } } else{ for(var i in lib.mode[name].connect){ if(i=='update') continue; lib.configOL[i.slice(8)]=get.config(i); } lib.configOL.zhinang_tricks=lib.config.connect_zhinang_tricks; lib.configOL.characterPack=lib.connectCharacterPack.slice(0); lib.configOL.cardPack=lib.connectCardPack.slice(0); for(var i=0;i3){ event.side=0; } event.goto(2); } else{ event.promptbar.hide(); event.side++; if(event.side>3){ event.side=0; } if(event.side>=2){ game.delay() } } 'step 4' if(event.checkredo()) return; if(event.skipnode) event.skipnode.delete(); if(event.replacenode) event.replacenode.delete(); if(event.reselectnode) event.reselectnode.delete(); if(event.freechoosenode) event.freechoosenode.delete(); for(var i=0;ievent.config.width){ event.avatars[i].classList.add('selecting'); } } var rand=[]; for(var i=0;i{ game.broadcastAll((roundNumber,pileTop,pileNumber)=>{ if(game.roundNumber!=roundNumber) game.roundNumber=roundNumber; if(_status.pileTop!=pileTop) _status.pileTop=pileTop; ui.updateRoundNumber(roundNumber,pileNumber); },game.roundNumber,ui.cardPile.firstChild,ui.cardPile.childElementCount); }, asyncDraw:(players,num,drawDeck,bottom)=>players.forEach((value,index)=>{ let num2=1; if(typeof num=='number') num2=num; else if(Array.isArray(num)) num2=num[index]; else if(typeof num=='function') num2=num(value); if(drawDeck&&drawDeck.drawDeck) value.draw(num2,false,drawDeck); else if(bottom) value.draw(num2,'nodelay','bottom'); else value.draw(num2,'nodelay'); }), asyncDrawAuto:function(players,num,drawDeck){ if(players.length>1){ game.asyncDraw.apply(this,arguments); return; } let num2=1; if(typeof num=='number') num2=num; else if(Array.isArray(num)) num2=num[0]; else if(typeof num=='function') num2=num(players[0]); if(drawDeck&&drawDeck.drawDeck) players[0].draw(num2,drawDeck); else players[0].draw(num2); }, finishSkill:(i,sub)=>{ const mode=get.mode(),info=lib.skill[i],iInfo=`${i}_info`; if(info.alter){ lib.translate[`${iInfo}_origin`]=lib.translate[iInfo]; if(!lib.config.vintageSkills.contains(i)) lib.translate[iInfo]=lib.translate[`${iInfo}_alter`]; } else if(lib.translate[`${iInfo}_${mode}`]) lib.translate[iInfo]=lib.translate[`${iInfo}_${mode}`]; else if(lib.translate[`${iInfo}_zhu`]&&(mode=='identity'||mode=='guozhan'&&_status.mode=='four')) lib.translate[iInfo]=lib.translate[`${iInfo}_zhu`]; else if(lib.translate[`${iInfo}_combat`]&&get.is.versus()) lib.translate[iInfo]=lib.translate[`${iInfo}_combat`]; if(info.forbid&&info.forbid.contains(mode)){ lib.skill[i]={}; if(lib.translate[iInfo]) lib.translate[iInfo]='此模式下不可用'; if(lib.dynamicTranslate[i]) lib.dynamicTranslate[i]=()=>'此模式下不可用'; return; } if(info.mode&&info.mode.contains(mode)==false){ lib.skill[i]={}; if(lib.translate[iInfo]) lib.translate[iInfo]='此模式下不可用'; if(lib.dynamicTranslate[i]) lib.dynamicTranslate[i]=()=>'此模式下不可用'; return; } if(info.available&&info.available(mode)==false){ lib.skill[i]={}; if(lib.translate[iInfo]) lib.translate[iInfo]='此模式下不可用'; if(lib.dynamicTranslate[i]) lib.dynamicTranslate[i]=()=>'此模式下不可用'; return; } if(info.viewAs&&typeof info.viewAs!='function'){ if(typeof info.viewAs=='string') info.viewAs={ name:info.viewAs }; if(!lib.card[info.viewAs.name]){ lib.skill[i]={}; lib.translate[iInfo]='技能不可用'; return; } if(info.ai==undefined) info.ai={}; const skill=info.ai,card=lib.card[info.viewAs.name].ai; if(card) Object.keys(card).forEach(value=>{ if(skill[value]==undefined) skill[value]=card[value]; else if(typeof skill[value]=='object') Object.keys(card[value]).forEach(element=>{ if(skill[value][element]==undefined) skill[value][element]=card[value][element]; }); }); } if(info.inherit){ const skill=lib.skill[info.inherit]; if(skill) Object.keys(skill).forEach(value=>{ if(info[value]!=undefined) return; if(value=='audio'&&(typeof info[value]=='number'||typeof info[value]=='boolean')) info[value]=info.inherit; else info[value]=skill[value]; }); if(lib.translate[i]==undefined) lib.translate[i]=lib.translate[info.inherit]; if(lib.translate[iInfo]==undefined) lib.translate[iInfo]=lib.translate[`${info.inherit}_info`]; } if(info.limited){ if(info.mark===undefined) info.mark=true; if(!info.intro) info.intro={}; if(info.intro.content===undefined) info.intro.content='limited'; if(info.skillAnimation===undefined) info.skillAnimation=true; if(info.init===undefined) info.init=(player,skill)=>player.storage[skill]=false; } if(info.subSkill&&!sub) Object.keys(info.subSkill).forEach(value=>{ const iValue=`${i}_${value}`; lib.skill[iValue]=info.subSkill[value]; lib.skill[iValue].sub=true; if(info.subSkill[value].name) lib.translate[iValue]=info.subSkill[value].name; else lib.translate[iValue]=lib.translate[iValue]||lib.translate[i]; if(info.subSkill[value].description) lib.translate[`${iValue}_info`]=info.subSkill[value].description; if(info.subSkill[value].marktext) lib.translate[`${iValue}_bg`]=info.subSkill[value].marktext; game.finishSkill(iValue,true); }); if(info.round){ const k=`${i}_roundcount`; if(typeof info.group=='string') info.group=[info.group,k]; else if(Array.isArray(info.group)) info.group.add(k); else info.group=[k]; lib.skill[k]=((round,name)=>({ init:player=>{ if(typeof player.storage[name]!=='number') player.storage[name]=1-round; }, intro:{ content:(storage,player)=>{ let str=''; const info=get.info(name.slice(0,name.indexOf('_roundcount'))); if(info&&info.addintro) str+=info.addintro(storage,player); const num=round-(game.roundNumber-storage); if(num>0) str+=`${get.cnNumber(num)}轮后${info.roundtext||'技能重置'}`; else str+='技能可发动'; return str; }, markcount:(storage,player)=>Math.max(round-(game.roundNumber-storage),0) }, trigger:{global:'roundStart'}, forced:true, popup:false, silent:true, content:()=>{ if(lib.skill[event.name.slice(0,event.name.indexOf('_roundcount'))].round-(game.roundNumber-player.storage[event.name])>0) player.updateMarks(); else player.unmarkSkill(event.name); } }))(info.round,k); lib.translate[k]=lib.translate[i]||''; lib.translate[`${k}_bg`]=lib.translate[`${i}_bg`]||lib.translate[k][0]; } if(info.marktext) lib.translate[`${i}_bg`]=info.marktext; if(info.silent){ if(!info.hasOwnProperty('forced')) info.forced=true; if(!info.hasOwnProperty('popup')) info.popup=false; } if(!info.hasOwnProperty('_priority')){ let priority=0; if(info.priority){ priority=info.priority*100; } if(info.silent){ priority++; } if(info.equipSkill) priority-=25; if(info.cardSkill) priority-=50; if(info.ruleSkill) priority-=75; info._priority=priority; } if(i[0]=='_') game.addGlobalSkill(i); }, finishCards:()=>{ _status.cardsFinished=true; const mode=get.mode(),filterTarget=(card,player,target)=>player==target&&target.canEquip(card,true),aiBasicOrder=(card,player)=>{ const equipValue=get.equipValue(card,player)/20; return player&&player.hasSkillTag('reverseEquip')?8.5-equipValue:8+equipValue; },aiBasicValue=(card,player,index,method)=>{ if(!player.getCards('e').contains(card)&&!player.canEquip(card,true)) return 0.01; const info=get.info(card),current=player.getEquip(info.subtype),value=current&&card!=current&&get.value(current,player); let equipValue=info.ai.equipValue||info.ai.basic.equipValue; if(typeof equipValue=='function'){ if(method=='raw')return equipValue(card,player); if(method=='raw2')return equipValue(card,player)-value; return Math.max(0.1,equipValue(card,player)-value); } if(typeof equipValue!='number') equipValue=0; if(method=='raw') return equipValue; if(method=='raw2') return equipValue-value; return Math.max(0.1,equipValue-value); },aiResultTarget=(player,target,card)=>get.equipResult(player,target,card.name); Object.keys(lib.card).forEach(libCardKey=>{ const info = `${libCardKey}_info`; if(lib.translate[`${info}_${mode}`]) lib.translate[info]=lib.translate[`${info}_${mode}`]; else if(lib.translate[`${info}_zhu`]&&(mode=='identity'||mode=='guozhan'&&_status.mode=='four')) lib.translate[info]=lib.translate[`${info}_zhu`]; else if(lib.translate[`${info}_combat`]&&get.is.versus()) lib.translate[info]=lib.translate[`${info}_combat`]; const card=lib.card[libCardKey]; if(card.filterTarget&&card.selectTarget==undefined) card.selectTarget=1; if(card.autoViewAs){ if(!card.ai) card.ai={}; if(!card.ai.order){ card.ai.order=lib.card[card.autoViewAs].ai.order; if(!card.ai.order&&lib.card[card.autoViewAs].ai.basic) card.ai.order=lib.card[card.autoViewAs].ai.basic.order; } } if(card.type=='equip'){ if(card.enable==undefined) card.enable=true; if(card.selectTarget==undefined) card.selectTarget=-1; if(card.filterTarget==undefined) card.filterTarget=filterTarget; if(card.modTarget==undefined) card.modTarget=true; if(card.allowMultiple==undefined) card.allowMultiple=false; if(card.content==undefined) card.content=lib.element.content.equipCard; if(card.toself==undefined) card.toself=true; if(card.ai==undefined) card.ai={ basic:{} }; if(card.ai.basic==undefined) card.ai.basic={}; if(card.ai.result==undefined) card.ai.result={ target:1.5 }; if(card.ai.basic.order==undefined) card.ai.basic.order=aiBasicOrder; if(card.ai.basic.useful==undefined) card.ai.basic.useful=2; if(card.subtype=='equip3'){ if(card.ai.basic.equipValue==undefined) card.ai.basic.equipValue=7; } else if(card.subtype=='equip4'){ if(card.ai.basic.equipValue==undefined) card.ai.basic.equipValue=4; } else if(card.ai.basic.equipValue==undefined) card.ai.basic.equipValue=1; if(card.ai.basic.value==undefined) card.ai.basic.value=aiBasicValue; if(!card.ai.result.keepAI) card.ai.result.target=aiResultTarget; } else if(card.type=='delay'){ if(card.enable==undefined) card.enable=true; if(card.filterTarget==undefined) card.filterTarget=lib.filter.judge; if(card.content==undefined) card.content=lib.element.content.addJudgeCard; if(card.allowMultiple==undefined) card.allowMultiple=false; } }); Object.keys(lib.skill).forEach(value=>game.finishSkill(value)); }, checkMod:function(){ const argumentArray=Array.from(arguments),name=argumentArray[argumentArray.length-2]; let skills=argumentArray[argumentArray.length-1]; if(typeof skills.getModableSkills == 'function'){ skills=skills.getModableSkills(_status.event.useCache === true); }else if(typeof skills.getSkills == 'function'){ skills=skills.getSkills().concat(lib.skill.global); game.expandSkills(skills); skills = skills.filter(function(skill){ var info = get.info(skill); return info && info.mod; }); skills.sort((a,b)=>get.priority(a)-get.priority(b)); } const arg=argumentArray.slice(0,-2); skills.forEach(value=>{ var mod = get.info(value).mod[name]; if(!mod)return; const result=mod.apply(this,arg); if(typeof arg[arg.length-1]!='object'&&result!=undefined) arg[arg.length-1]=result; }); return arg[arg.length-1]; }, prepareArena:num=>{ _status.prepareArena=true; game.showHistory(false); ui.create.players(num); ui.create.me(); ui.create.cardsAsync(); game.finishCards(); }, clearArena:()=>{ ui.control.innerHTML=''; ui.arenalog.innerHTML=''; Array.from(ui.arena.childNodes).forEach(value=>{ if(value==ui.canvas) return; if(value==ui.control) return; if(value==ui.arenalog) return; if(value==ui.roundmenu) return; if(value==ui.timer) return; if(value==ui.autonode) return; value.remove(); }); ui.sidebar.innerHTML=''; ui.cardPile.innerHTML=''; ui.discardPile.innerHTML=''; ui.special.innerHTML=''; ui.ordering.innerHTML=''; ui.playerids.remove(); game.players.length=0; game.dead.length=0; game.me=null; }, clearConnect:()=>{ if(ui.ipnode){ ui.ipnode.remove(); delete ui.ipnode; } if(ui.iptext){ ui.iptext.remove(); delete ui.iptext; } if(ui.ipbutton){ ui.ipbutton.remove(); delete ui.ipbutton; } if(ui.recentIP){ ui.recentIP.remove(); delete ui.recentIP; } if(ui.hall_button){ ui.hall_button.remove(); delete ui.hall_button; } if(ui.startServer){ ui.startServer.remove(); delete ui.startServer; } if(ui.rooms){ ui.rooms.forEach(value=>value.remove()); delete ui.rooms; } if(ui.roombase){ ui.roombase.remove(); delete ui.roombase; } if(!ui.connectEvents) return; ui.connectEvents.remove(); ui.connectEventsCount.remove(); ui.connectClients.remove(); ui.connectClientsCount.remove(); ui.createRoomButton.remove(); delete ui.connectEvents; delete ui.connectEventsCount; delete ui.connectClients; delete ui.connectClientsCount; delete ui.createRoomButton; }, log:function(){ let str='',str2='',logvid=null; const color=new Map([ ['r','fire'], ['y','yellow'], ['g','green'], ['b','blue'] ]); Array.from(arguments).forEach(value=>{ const itemtype=get.itemtype(value); if(itemtype=='player'||itemtype=='players'){ str+=`${get.translation(value)}`; str2+=get.translation(value); } else if(itemtype=='cards'||itemtype=='card'||(typeof value=='object'&&value&&value.name)){ str+=`${get.translation(value)}`; str2+=get.translation(value); } else if(typeof value=='object'){ if(value.parentNode==ui.historybar) logvid=value.logvid; else{ str+=get.translation(value); str2+=get.translation(value); } } else if(typeof value=='string'){ if(value[0]=='【'&&value[value.length-1]=='】'){ str+=`${get.translation(value)}`; str2+=get.translation(value); } else if(value[0]=='#'){ str+=`${get.translation(value.slice(2))}`; str2+=get.translation(value.slice(2)); } else{ str+=get.translation(value); str2+=get.translation(value); } } else{ str+=value; str2+=value; } }); const node=ui.create.div(); node.innerHTML=lib.config.log_highlight?str:str2; ui.sidebar.insertBefore(node,ui.sidebar.firstChild); game.addVideo('log',null,lib.config.log_highlight?str:str2); game.broadcast((str,str2)=>game.log(lib.config.log_highlight?str:str2),str,str2); if(!_status.video&&!game.online){ if(logvid) game.logv(logvid,`
        ${lib.config.log_highlight?str:str2}
        `); else logvid=_status.event.getLogv(); } if(lib.config.show_log=='off'||game.chess) return; const nodeentry=node.cloneNode(true); ui.arenalog.insertBefore(nodeentry,ui.arenalog.firstChild); if(!lib.config.clear_log) while(ui.arenalog.childNodes.length&&ui.arenalog.scrollHeight>ui.arenalog.offsetHeight){ ui.arenalog.lastChild.remove(); } if(!lib.config.low_performance){ nodeentry.style.transition='all 0s'; nodeentry.style.marginBottom=`-${nodeentry.offsetHeight}px`; ui.refresh(nodeentry); nodeentry.style.transition=''; nodeentry.style.marginBottom=''; } if(!lib.config.clear_log) return; nodeentry.timeout=setTimeout(()=>nodeentry.delete(),1000); Array.from(ui.arenalog.childNodes).forEach(value=>{ if(!value.timeout) value.remove(); }); }, logv:(player,card,targets,event,forced,logvid)=>{ if(!player){ player=_status.event.getParent().logvid; if(!player) return; } const node=ui.create.div('.hidden'); node.node={}; logvid=logvid||get.id(); game.broadcast(game.logv,player,card,targets,event,forced,logvid); if(typeof player=='string'){ const childNode=Array.from(ui.historybar.childNodes).find(value=>value.logvid==player); if(childNode) childNode.added.push(card); return; } if(typeof card=='string'){ if(card!='die'){ if(lib.skill[card]&&lib.skill[card].logv===false&&!forced) return; if(!lib.translate[card]) return; } let avatar; if(!player.isUnseen(0)) avatar=player.node.avatar.cloneNode(); else if(!player.isUnseen(1)) avatar=player.node.avatar2.cloneNode(); else return; node.node.avatar=avatar; avatar.style.transform=''; avatar.className='avatar'; if(card=='die'){ node.dead=true; node.player=player; const avatar2=avatar.cloneNode(); avatar2.className='avatarbg grayscale1'; avatar.appendChild(avatar2); avatar.style.opacity=0.6; } else{ node.node.text=ui.create.div('',get.translation(card,'skill'),avatar); node.node.text.dataset.nature='water'; node.skill=card; } node.appendChild(avatar); if(card=='die'&&targets&&targets!=player){ node.source=targets; player=targets; if(!player.isUnseen(0)) avatar=player.node.avatar.cloneNode(); else if(!player.isUnseen(1)) avatar=player.node.avatar2.cloneNode(); else if(get.mode()=='guozhan'&&player.node&&player.node.name_seat){ avatar=ui.create.div('.avatar.cardbg'); avatar.innerHTML=player.node.name_seat.innerHTML[0]; } else return; avatar.style.transform=''; node.node.avatar2=avatar; avatar.classList.add('avatar2'); node.appendChild(avatar); } } else if(Array.isArray(card)){ node.cards=card[1].slice(0) card=card[0]; const info=[card.suit||'',card.number||'',card.name||'',card.nature||'']; if(!Array.isArray(node.cards)||!node.cards.length) node.cards=[ui.create.card(node,'noclick',true).init(info)]; if(card.name=='wuxie'){ if(ui.historybar.firstChild&&ui.historybar.firstChild.type=='wuxie'){ ui.historybar.firstChild.players.push(player); ui.historybar.firstChild.cards.addArray(node.cards); return; } node.type='wuxie'; node.players=[player]; } if(card.copy) card.copy(node,false); else{ card=ui.create.card(node,'noclick',true); card.init(info); } let avatar; if(!player.isUnseen(0)) avatar=player.node.avatar.cloneNode(); else if(!player.isUnseen(1)) avatar=player.node.avatar2.cloneNode(); else if(get.mode()=='guozhan'&&player.node&&player.node.name_seat){ avatar=ui.create.div('.avatar.cardbg'); avatar.innerHTML=player.node.name_seat.innerHTML[0]; } else return; node.node.avatar=avatar; avatar.style.transform=''; avatar.classList.add('avatar2'); node.appendChild(avatar); if(targets&&targets.length==1&&targets[0]!=player&&get.itemtype(targets[0])=='player') (()=>{ let avatar2; const target=targets[0]; if(!target.isUnseen(0)) avatar2=target.node.avatar.cloneNode(); else if(!player.isUnseen(1)) avatar2=target.node.avatar2.cloneNode(); else if(get.mode()=='guozhan'&&target.node&&target.node.name_seat){ avatar2=ui.create.div('.avatar.cardbg'); avatar2.innerHTML=target.node.name_seat.innerHTML[0]; } else return; node.node.avatar2=avatar2; avatar2.style.transform=''; avatar2.classList.add('avatar2'); avatar2.classList.add('avatar3'); node.insertBefore(avatar2,avatar); })(); } if(targets&&targets.length){ if(targets.length==1&&targets[0]==player){ node.targets=[]; } else{ node.targets=targets; } } const fullheight=ui.historybar.offsetHeight,num=Math.round((fullheight-8)/50),margin=(fullheight-42*num)/(num+1); node.style.transform='scale(0.8)'; ui.historybar.insertBefore(node,ui.historybar.firstChild); ui.refresh(node); node.classList.remove('hidden'); Array.from(ui.historybar.childNodes).forEach((value,index)=>{ if(index()=>current.remove())(value),500); }); if(lib.config.touchscreen) node.addEventListener('touchstart',ui.click.intro); else{ node.addEventListener(lib.config.pop_logv?'mousemove':'click',ui.click.logv); node.addEventListener('mouseleave',ui.click.logvleave); } node.logvid=logvid; node.added=[]; if(!game.online){ event=event||_status.event; event.logvid=node.logvid; } return node; }, putDB:(storeName,idbValidKey,value,onSuccess,onError)=>{ if(!lib.db) return Promise.resolve(value); if(lib.status.reload) return new Promise((resolve,reject)=>lib[_status.dburgent?'ondb2':'ondb'].push(['putDB',[storeName,idbValidKey,value,event=>{ if(typeof onSuccess=='function') onSuccess(event); resolve(event); },event=>{ if(typeof onError=='function'){ onError(event); resolve(); } else reject(event); }]])); lib.status.reload++; return new Promise((resolve,reject)=>{ const record=lib.db.transaction([storeName],'readwrite').objectStore(storeName).put(value,idbValidKey); record.onerror=event=>{ if(typeof onError=='function'){ onError(event); game.reload2(); resolve(); } else{ game.reload2(); reject(event); } };; record.onsuccess=event=>{ if(typeof onSuccess=='function'){ _status.dburgent=true; onSuccess(event); delete _status.dburgent; } game.reload2(); resolve(event); }; }); }, getDB:(storeName,query,onSuccess,onError)=>{ if(!lib.db) return new Promise(resolve=>{ if(typeof onSuccess=='function') onSuccess(null); resolve(null); }); if(lib.status.reload) return new Promise((resolve,reject)=>lib[_status.dburgent?'ondb2':'ondb'].push(['getDB',[storeName,query,result=>{ if(typeof onSuccess=='function') onSuccess(result); resolve(result); },event=>{ if(typeof onError=='function'){ onError(event); resolve(); } else reject(event); }]])); return new Promise(query?(resolve,reject)=>{ lib.status.reload++; const idbRequest=lib.db.transaction([storeName],'readwrite').objectStore(storeName).get(query); idbRequest.onerror=event=>{ if(typeof onError=='function'){ onError(event); game.reload2(); resolve(); } else{ game.reload2(); reject(event); } };; idbRequest.onsuccess=event=>{ const result=event.target.result; if(typeof onSuccess=='function'){ _status.dburgent=true; onSuccess(result); delete _status.dburgent; } game.reload2(); resolve(result); }; }:(resolve,reject)=>{ lib.status.reload++; const idbRequest=lib.db.transaction([storeName],'readwrite').objectStore(storeName).openCursor(),object={}; idbRequest.onerror=event=>{ if(typeof onError=='function'){ onError(event); game.reload2(); resolve(); } else{ game.reload2(); reject(event); } };; idbRequest.onsuccess=event=>{ const result=event.target.result; if(result){ object[result.key]=result.value; result.continue(); return; } if(typeof onSuccess=='function'){ _status.dburgent=true; onSuccess(object); delete _status.dburgent; } game.reload2(); resolve(object); }; }); }, deleteDB:(storeName,query,onSuccess,onError)=>{ if(!lib.db) return new Promise(resolve=>{ if(typeof onSuccess=='function') onSuccess(false); resolve(false); }); if(lib.status.reload) return new Promise((resolve,reject)=>lib[_status.dburgent?'ondb2':'ondb'].push(['deleteDB',[storeName,query,event=>{ if(typeof onSuccess=='function') onSuccess(event); resolve(event); },event=>{ if(typeof onError=='function'){ onError(event); resolve(); } else reject(event); }]])); return query?new Promise((resolve,reject)=>{ lib.status.reload++; const record=lib.db.transaction([storeName],'readwrite').objectStore(storeName).delete(query); record.onerror=event=>{ if(typeof onError=='function'){ onError(event); game.reload2(); resolve(); } else{ game.reload2(); reject(event); } }; record.onsuccess=event=>{ if(typeof onSuccess=='function') onSuccess(event); game.reload2(); resolve(event); }; }):game.getDB(storeName).then(object=>{ const keys=Object.keys(object); lib.status.reload+=keys.length; const store=lib.db.transaction([storeName],'readwrite').objectStore(storeName); return Promise.allSettled(keys.map(key=>new Promise((resolve,reject)=>{ const request=store.delete(key); request.onerror=event=>{ game.reload2(); reject(event); };; request.onsuccess=event=>{ game.reload2(); resolve(event); }; }))); }); }, save:(key,value,mode)=>{ if(_status.reloading) return; mode=mode||lib.config.mode; if(lib.db){ if(!key){ game.putDB('data',mode,get.copy(lib.storage)); return; } if(mode==lib.config.mode){ if(value==undefined) delete lib.storage[key]; else lib.storage[key]=value; lib.storage.version=lib.version; game.putDB('data',mode,lib.storage); } else game.getDB('data',mode,config=>{ if(!config) config={}; if(value==undefined) delete config[key]; else config[key]=value; config.version=lib.version; game.putDB('data',mode,config); }); return; } if(!key){ localStorage.setItem(`${lib.configprefix}${mode}`,JSON.stringify(lib.storage)); return; } let config; try{ config=JSON.parse(localStorage.getItem(`${lib.configprefix}${mode}`)); if(typeof config!='object') throw 'err'; } catch(err){ config={}; } if(value==undefined){ delete config[key]; if(mode==lib.config.mode) delete lib.storage[key]; } else{ config[key]=value; if(mode==lib.config.mode) lib.storage[key]=value; } config.version=lib.version; localStorage.setItem(`${lib.configprefix}${mode}`,JSON.stringify(config)); }, showChangeLog:()=>{ if(lib.version==lib.config.version&&!_status.extensionChangeLog) return; const ul=document.createElement('ul'); ul.style.textAlign='left'; const caption=lib.version==lib.config.version?'扩展更新':`${lib.version}更新内容`; let players=null,cards=null; if(lib.version!=lib.config.version) lib.changeLog.forEach(value=>{ if(value.startsWith('players://')) try{ players=JSON.parse(value.slice(10)).filter(value=>lib.character[value]); } catch(e){ players=null; } else if(value.startsWith('cards://')) try{ cards=JSON.parse(value.slice(8)).filter(value=>lib.card[value]); } catch(e){ cards=null; } else{ const li=document.createElement('li'); li.innerHTML=value; ul.appendChild(li); } }); game.saveConfig('version',lib.version); if(_status.extensionChangeLog) Object.keys(_status.extensionChangeLog).forEach(value=>{ const li=document.createElement('li'); li.innerHTML=`${value}:${_status.extensionChangeLog[value]}`; ul.appendChild(li); }); const dialog=ui.create.dialog(caption,'hidden'),lic=ui.create.div(dialog.content); lic.style.display='block'; ul.style.display='inline-block'; ul.style.marginLeft='-40px'; lic.appendChild(ul); if(players&&players.length){ dialog.addSmall([players,'character']); dialog.classList.add('forcebutton'); dialog.classList.add('withbg'); } if(cards&&cards.length){ dialog.addSmall([cards.map(value=>[get.translation(get.type(value)),'',value]),'vcard']); dialog.classList.add('forcebutton'); dialog.classList.add('withbg'); } dialog.open(); let hidden=false; if(!ui.auto.classList.contains('hidden')){ ui.auto.hide(); hidden=true; } game.pause(); const control=ui.create.control('确定',()=>{ dialog.close(); control.close(); if(hidden) ui.auto.show(); game.resume(); }); lib.init.onfree(); }, showExtensionChangeLog:(str,extname)=>{ extname=extname||_status.extension; const cfg=`extension_${extname}_changelog`; if(!lib.extensionPack[extname]||lib.extensionPack[extname].version==lib.config[cfg]) return; game.saveConfig(cfg,lib.extensionPack[extname].version); if(_status.extensionChangeLog) return; _status.extensionChangeLog={}; _status.extensionChangeLog[extname]=str; }, saveConfig:(key,value,local,callback)=>{ if(_status.reloading) return; if(local){ const localmode=typeof local=='string'?local:lib.config.mode; if(!lib.config.mode_config[localmode]) lib.config.mode_config[localmode]={}; if(value==undefined) delete lib.config.mode_config[localmode][key]; else lib.config.mode_config[localmode][key]=value; key+=`_mode_config_${localmode}`; } else if(value==undefined) delete lib.config[key]; else lib.config[key]=value; if(lib.db){ if(value==undefined) game.deleteDB('config',key,callback); else game.putDB('config',key,value,callback); return; } let config; try{ config=JSON.parse(localStorage.getItem(`${lib.configprefix}config`)); if(!config||typeof config!='object') throw 'err'; } catch(err){ config={}; } if(value===undefined) delete config[key]; else config[key]=value; localStorage.setItem(`${lib.configprefix}config`,JSON.stringify(config)); if(callback) callback(); }, saveConfigValue:key=>game.saveConfig(key,lib.config[key]), saveExtensionConfig:(extension,key,value)=>game.saveConfig(`extension_${extension}_${key}`,value), saveExtensionConfigValue:(extension,key)=>game.saveExtensionConfig(extension,key,game.getExtensionConfig(extension,key)), getExtensionConfig:(extension,key)=>lib.config[`extension_${extension}_${key}`], clearModeConfig:mode=>{ if(_status.reloading) return; if(lib.db){ game.getDB('config',null,config=>Object.keys(config).forEach(value=>{ if(value.substr(value.indexOf('_mode_config')+13)==mode) game.saveConfig(value); })); return; } let config; try{ config=JSON.parse(localStorage.getItem(`${lib.configprefix}config`)); if(!config||typeof config!='object') throw 'err'; } catch(err){ config={}; } Object.keys(config).forEach(value=>{ if(value.substr(value.indexOf('_mode_config')+13)==mode) delete config[value]; }); localStorage.setItem(`${lib.configprefix}config`,JSON.stringify(config)); localStorage.removeItem(`${lib.configprefix}${mode}`); }, addPlayer:(position,character,character2)=>{ if(position<0||position>game.players.length+game.dead.length||position==undefined) position=Math.ceil(Math.random()*(game.players.length+game.dead.length)); const players=game.players.concat(game.dead); ui.arena.setNumber(players.length+1); players.forEach(value=>{ if(parseInt(value.dataset.position)>=position) value.dataset.position=parseInt(value.dataset.position)+1; }); const player=ui.create.player(ui.arena).animate('start'); if(character) player.init(character,character2); game.players.push(player); player.dataset.position=position; game.arrangePlayers(); return player; }, addFellow:(position,character,animation)=>{ game.addVideo('addFellow',null,[position,character,animation]); const player=ui.create.player(ui.arena).animate(animation||'start'); player.dataset.position=position||game.players.length+game.dead.length; player.getId(); if(character) player.init(character); game.players.push(player); game.arrangePlayers(); return player; }, triggerEnter:player=>{ const next=game.createEvent('enterGame',false); next.player=player; next.setContent(()=>{ event.trigger('enterGame'); }); return next; }, restorePlayer:player=>{ if(game.players.contains(player)||game.dead.contains(player)) return; let position=parseInt(player.dataset.position); if(position<0||position>game.players.length+game.dead.length||position==undefined) position=Math.ceil(Math.random()*(game.players.length+game.dead.length)); const players=game.players.concat(game.dead); ui.arena.setNumber(players.length+1); players.forEach(value=>{ if(parseInt(value.dataset.position)>=position) value.dataset.position=parseInt(value.dataset.position)+1; }); game.players.push(player); delete player.removed; player.removeAttribute('style'); player.animate('start'); ui.arena.appendChild(player); game.arrangePlayers(); return player; }, removePlayer:player=>{ if(_status.roundStart==player) _status.roundStart=player.next||player.getNext()||game.players[0]; const players=game.players.concat(game.dead); player.style.left=`${player.getLeft()}px`; player.style.top=`${player.getTop()}px`; if(player==undefined) player=game.dead[0]||game.me.next; const position=parseInt(player.dataset.position); players.forEach(value=>{ if(parseInt(value.dataset.position)>position) value.dataset.position=parseInt(value.dataset.position)-1; }); if(player.isAlive()){ player.next.previous=player.previous; player.previous.next=player.next; } player.nextSeat.previousSeat=player.previousSeat; player.previousSeat.nextSeat=player.nextSeat; player.delete(); game.players.remove(player); game.dead.remove(player); ui.arena.setNumber(players.length-1); player.removed=true; if(player==game.me){ ui.me.hide(); ui.auto.hide(); ui.wuxie.hide(); } setTimeout(()=>player.removeAttribute('style'),500); return player; }, replacePlayer:(player,character,character2)=>{ player.removed=true; const position=parseInt(player.dataset.position); game.players.remove(player); game.dead.remove(player); player.delete(); const player2=ui.create.player(ui.arena).animate('start'); if(character) player2.init(character,character2); game.players.push(player2); player2.dataset.position=position; player2.nextSeat=player.nextSeat; player2.previousSeat=player.previousSeat; player2.nextSeat.previousSeat=player2; player2.previousSeat.nextSeat=player2; let player3=player2.nextSeat; while(player3.isDead()){ player3=player3.nextSeat; } player3.previous=player2; player2.next=player3; let player4=player2.previousSeat; while(player4.isDead()){ player4=player4.previousSeat; } player4.next=player2; player2.previous=player4; if(_status.roundStart==player) _status.roundStart=player2; return player2; }, arrangePlayers:()=>{ if(game.chess&&game.me){ let friendCount=0,enemyCount=0; const rand=Math.random()<0.5,sortCount=new Map(); game.players.forEach(value=>{ if(value.side==game.me.side){ if(rand) if(value==game.friendZhu) sortCount.set(value,-2); else sortCount.set(value,2*friendCount); else if(value==game.friendZhu) sortCount.set(value,-1); else sortCount.set(value,2*friendCount+1); friendCount++; return; } if(rand) if(value==game.enemyZhu) sortCount.set(value,-1); else sortCount.set(value,2*enemyCount+1); else if(value==game.enemyZhu) sortCount.set(value,-2); else sortCount.set(value,2*enemyCount); enemyCount++; }); game.players.sort((a,b)=>sortCount.get(a)-sortCount.get(b)); } else game.players.sort(lib.sort.position); game.players.concat(game.dead).sort(lib.sort.position).forEach((value,index,array)=>{ if(index==0) value.previousSeat=array[array.length-1]; else value.previousSeat=array[index-1]; if(index==array.length-1) value.nextSeat=array[0]; else value.nextSeat=array[index+1]; }); game.players.forEach((value,index,array)=>{ if(index==0) value.previous=array[array.length-1]; else value.previous=array[index-1]; if(index==array.length-1) value.next=array[0]; else value.next=array[index+1]; }); }, filterSkills:(skills,player,exclude)=>{ const out=skills.slice().removeArray(Object.keys(player.disabledSkills)); if(!player.storage.skill_blocker||!player.storage.skill_blocker.length) return out; return out.filter(value=>exclude&&exclude.includes(value)||!get.is.blocked(value,player)); }, expandSkills:skills=>skills.addArray(skills.reduce((previousValue,currentValue)=>{ const info=get.info(currentValue); if(info){ if(Array.isArray(info.group)) previousValue.push(...info.group); else if(info.group) previousValue.push(info.group); } else console.log(currentValue); return previousValue; },[])), css:style=>Object.keys(style).forEach(value=>{ let uiStyle=ui.style[value]; if(!uiStyle){ uiStyle=ui.style[value]=document.createElement('style'); document.head.appendChild(uiStyle); } uiStyle.innerHTML=`${value}${JSON.stringify(style[value]).replace(/"/g,"")}`; }), hasPlayer:(func,includeOut)=>game.players.some(value=>(includeOut||!value.isOut())&&func(value)), hasPlayer2:(func,includeOut)=>game.players.concat(game.dead).some(value=>(includeOut||!value.isOut())&&func(value)), countPlayer:(func,includeOut)=>{ if(typeof func!='function') func=lib.filter.all; return game.players.reduce((previousValue,currentValue)=>{ if(!includeOut&¤tValue.isOut()) return previousValue; const result=func(currentValue); if(typeof result=='number') previousValue+=result; else if(result) previousValue++; return previousValue; },0); }, countPlayer2:(func,includeOut)=>{ if(typeof func!='function') func=lib.filter.all; return game.players.concat(game.dead).reduce((previousValue,currentValue)=>{ if(!includeOut&¤tValue.isOut()) return previousValue; const result=func(currentValue); if(typeof result=='number') previousValue+=result; else if(result) previousValue++; return previousValue; },0); }, filterPlayer:(func,list,includeOut)=>{ if(!Array.isArray(list)) list=[]; if(typeof func!='function') func=lib.filter.all; return list.addArray(game.players.filter(value=>(includeOut||!value.isOut())&&func(value))); }, filterPlayer2:(func,list,includeOut)=>{ if(!Array.isArray(list)) list=[]; if(typeof func!='function') func=lib.filter.all; return list.addArray(game.players.concat(game.dead).filter(value=>(includeOut||!value.isOut())&&func(value))); }, findPlayer:(func,includeOut)=>game.players.find(value=>(includeOut||!value.isOut())&&func(value))||null, findPlayer2:(func,includeOut)=>game.players.concat(game.dead).find(value=>(includeOut||!value.isOut())&&func(value))||null, findCards:(func,all)=>Object.keys(lib.card).filter(value=>{ if(!lib.translate[`${value}_info`]) return false; if(lib.card[value].mode&&lib.card[value].mode.includes(lib.config.mode)==false) return false; if(!all&&!lib.inpile.includes(value)) return false; return func(value,lib.card[value]); }), countGroup:()=>{ const list=lib.group.slice(0); return game.countPlayer(current=>{ if(!list.includes(current.group)) return false; list.remove(current.group); return true; }); }, /** * @type {Player[]} */ players:[], /** * @type {Player[]} */ dead:[], imported:[], playerMap:{}, phaseNumber:0, roundNumber:0, shuffleNumber:0, }; window['b'+'ann'+'e'+'dE'+'x'+'ten'+'s'+'i'+'o'+'ns']=['\u4fa0\u4e49','\u5168\u6559\u7a0b']; const ui={ updates:[], thrown:[], touchlines:[], todiscard:{}, /** * @type {HTMLStyleElement[]} */ playerPositions:[], refresh:function(node){ void window.getComputedStyle(node, null).getPropertyValue("opacity"); }, create:{ //创建身份牌实例 identityCard:function(identity,position,noclick){ const card=ui.create.card(position,'noclick',noclick); card.classList.add('button'); card._customintro=uiintro=>uiintro.add(`${get.translation(`${identity}${2}`)}的身份牌`); const fileName=`image/card/identity_${identity}.jpg`; new Promise((resolve,reject)=>{ const image=new Image(); image.onload=resolve; image.onerror=reject; image.src=`${lib.assetURL}${fileName}`; }).then(()=>{ card.classList.add('fullskin'); card.node.image.setBackgroundImage(fileName); },()=>card.node.background.innerHTML=get.translation(identity)[0]); return card; }, //让卡牌旋转 cardSpinning:function(card){ if(lib.config.cardback_style!='default'){ card.style.transitionProperty='none'; ui.refresh(card); card.classList.add('infohidden'); ui.refresh(card); card.style.transitionProperty=''; } else{ card.classList.add('infohidden'); } card.style.transition='all 0s'; card.style.transform='perspective(600px) rotateY(180deg) translateX(0)'; const onEnd01=function(){ setTimeout(function(){ card.style.transition='all ease-in 0.3s'; card.style.transform='perspective(600px) rotateY(270deg) translateX(52px)'; var onEnd=function(){ card.classList.remove('infohidden'); card.style.transition='all 0s'; ui.refresh(card); card.style.transform='perspective(600px) rotateY(-90deg) translateX(52px)'; ui.refresh(card); card.style.transition=''; ui.refresh(card); card.style.transform=''; } card.listenTransition(onEnd); },300); }; onEnd01(); }, //旋转的身份牌! spinningIdentityCard:function(identity,dialog){ const card=ui.create.identityCard(identity); const buttons=ui.create.div('.buttons',dialog.content); setTimeout(()=>{ buttons.appendChild(card); dialog.open(); ui.create.cardSpinning(card,time); },50); }, /** * 创建codemirror编辑器 * @param {HTMLDivElement} container * @param {Function} saveInput */ editor:function(container,saveInput){ const createList=[]; const containerDelete=container.delete; const editorpage=ui.create.div(container); //删除container的时候,删除创建的ul列表 container.delete=function(){ for (let i=createList.length-1;i>=0;i--){ createList[i].parentNode&&createList[i].parentNode.removeChild(createList[i]); } Array.from(editorpage.children).forEach(v=>{v.style.background=''}); containerDelete.apply(this, arguments); } //创建ul列表 const createMenu=function(pos,self,List,click){ if(!self||self==window) return; const parent=self.parentNode; if (parent){ for(let i=0;i{ let i=0; while(i{ ul.childNodes[getActive()].classList.remove('CodeMirror-hint-active'); ul.childNodes[i].classList.add('CodeMirror-hint-active'); return i; }; if (List&&List.length&&click) { for(let i=0;i{ setActive(i); }; } } createList.add(ul); ui.window.appendChild(ul); return ul; }; //关闭ul列表 const closeMenu=function(){ const ul=this.ul; if(!ul) return false; if(ul.parentNode) ul.parentNode.removeChild(ul); this.style.background=''; //创建后不用删除了,除非以后要动态加载。 //delete this.ul; createList.remove(ul); return ul; }; const discardConfig=ui.create.div('.editbutton','取消',editorpage,function(){ ui.window.classList.remove('shortcutpaused'); ui.window.classList.remove('systempaused'); container.delete(null); delete window.saveNonameInput; }); const saveConfig=ui.create.div('.editbutton','保存',editorpage,saveInput); const theme=ui.create.div('.editbutton','主题',editorpage,function(){ if(!this||this==window) return; if(this.ul&&this.ul.parentNode){ return closeMenu.call(this); } //this const self=this; if(!this.ul){ //主题列表 const list=['mdn-like','mbo']; //正在使用的主题 const active=container.editor.options.theme; //排个序 list.remove(active).splice(0,0,active); //元素位置 const pos=self.getBoundingClientRect(); //点击事件 const click=function(e){ const theme=this.innerHTML; container.editor.setOption("theme",theme); setTimeout(()=>container.editor.refresh(),0); game.saveConfig('codeMirror_theme',theme); closeMenu.call(self); }; const ul=createMenu(pos,self,list,click); self.ul=ul; }else{ createMenu(null,self); } }); const edit=ui.create.div('.editbutton','编辑',editorpage,function(){ if(!this||this==window) return; if(this.ul&&this.ul.parentNode){ return closeMenu.call(this); } const self=this; if(!this.ul){ const pos=this.getBoundingClientRect(); const list=['撤销 Ctrl+Z', '恢复撤销 Ctrl+Y']; const click=function(e){ const num=this.innerHTML.indexOf("Ctrl"); const inner=this.innerHTML.slice(num).replace("+", "-"); container.editor.execCommand(container.editor.options.extraKeys[inner]); setTimeout(()=>container.editor.refresh(),0); closeMenu.call(self); }; const ul=createMenu(pos,self,list,click); this.ul=ul; }else{ createMenu(null,self); } }); const fontSize=ui.create.div('.editbutton','字号',editorpage,function(){ if(!this||this==window) return; if(this.ul&&this.ul.parentNode){ return closeMenu.call(this); } const self=this; if(!this.ul){ const pos=this.getBoundingClientRect(); const list=['16px','18px','20px','22px','24px','26px']; const click=function(e){ const size=this.innerHTML; container.style.fontSize=size.slice(0,-2)/game.documentZoom+'px'; Array.from(self.parentElement.children).map(v=>v.ul).filter(Boolean).forEach(v=>{v.style.fontSize=size.slice(0,-2)/game.documentZoom+'px'}); setTimeout(()=>container.editor.refresh(),0); game.saveConfig('codeMirror_fontSize',size); closeMenu.call(self); }; const ul=createMenu(pos,self,list,click); this.ul=ul; }else{ createMenu(null,self); } }); const editor=ui.create.div(editorpage); return editor; }, cardTempName:function(card,applyNode){ let getApplyNode=applyNode||card; let cardName=get.name(card); let cardNature=get.nature(card); let tempname=get.translation(cardName); let cardTempNameConfig=lib.config.cardtempname; let node=getApplyNode._tempName||ui.create.div('.tempname',getApplyNode); let datasetNature=''; getApplyNode._tempName=node; if(cardTempNameConfig!='image'){ //清空,避免和下面的image部分有冲突 node.innerHTML=''; datasetNature='fire'; if(get.position(card)=='j'&&card.viewAs&&card.viewAs!=card.name) { datasetNature = 'wood'; tempname=get.translation(card.viewAs); }else{ if(cardName=='sha'){ if(cardNature) tempname=get.translation(cardNature)+tempname; if(cardNature=='thunder') datasetNature='thunder'; if(cardNature=='kami') datasetNature='kami'; if(cardNature=='ice') datasetNature='ice'; } } if(cardTempNameConfig=='default') getApplyNode._tempName.classList.add('vertical'); if(datasetNature.length>0){ node.dataset.nature=datasetNature; }else{ delete node.dataset.nature; node.classList.add(datasetNature); } }else{ if(get.position(card)=='j'&&card.viewAs&&card.viewAs!=card.name) { cardName=card.viewAs; tempname=get.translation(card.viewAs); } if(cardName=='sha'){ if(cardNature) tempname=get.translation(cardNature)+tempname; if(cardNature=='fire') datasetNature = 'fire'; if(cardNature=='thunder') datasetNature='thunder'; if(cardNature=='kami') datasetNature='kami'; if(cardNature=='ice') datasetNature='ice'; } let bg=node.querySelector('div'); if (bg) { Array.from(node.childNodes).filter(v=>v!=bg).forEach(v=>node.removeChild(v)); } else bg=ui.create.div(node); node.classList.add('tempimage'); let img=lib.card[cardName].image; if(img){ if(img.startsWith('db:')){ img=img.slice(3); } else if(!img.startsWith('ext:')){ img=null; } } if(lib.card[cardName].fullskin){ if(img){ if(img.startsWith('ext:')){ bg.setBackgroundImage(img.replace(/^ext:/,'extension/')); } else{ bg.setBackgroundDB(img); } } else{ if(lib.card[cardName].modeimage){ bg.setBackgroundImage('image/mode/'+lib.card[cardName].modeimage+'/card/'+cardName+'.png'); } else{ if(cardName=='sha'&&cardNature=='stab') bg.setBackgroundImage('image/card/cisha.png'); else bg.setBackgroundImage('image/card/'+cardName+'.png'); } } } else if(lib.card[cardName].image=='background'){ if(cardNature) bg.setBackground(cardName+'_'+cardNature,'card'); else bg.setBackground(cardName,'card'); } else if(lib.card[cardName].fullimage){ if(img){ if(img.startsWith('ext:')){ bg.setBackgroundImage(img.replace(/^ext:/,'extension/')); bg.style.backgroundSize='cover'; } else{ bg.setBackgroundDB(img); } } else if(lib.card[cardName].image){ if(lib.card[cardName].image.startsWith('character:')){ bg.setBackground(lib.card[cardName].image.slice(10),'character'); } else{ bg.setBackground(lib.card[cardName].image); } } else{ let cardPack=lib.cardPack['mode_'+get.mode()]; if(Array.isArray(cardPack)&&cardPack.contains(cardName)){ bg.setBackground('mode/'+get.mode()+'/card/'+cardName); } else{ bg.setBackground('card/'+cardName); } } } else if(lib.card[cardName].image=='card'){ if(cardNature) bg.setBackground(cardName+'_'+cardNature,'card'); else bg.setBackground(cardName,'card'); } else if(typeof lib.card[cardName].image=='string'&&!lib.card[cardName].fullskin){ if(img){ if(img.startsWith('ext:')){ bg.setBackgroundImage(img.replace(/^ext:/,'extension/')); bg.style.backgroundSize='cover'; } else{ bg.setBackgroundDB(img); } } else{ bg.setBackground(lib.card[cardName].image); } } else{ console.warn('卡牌图片解析失败'); } if(datasetNature.length>0){ node.classList.add(datasetNature); } delete node.dataset.nature; } node.innerHTML+=`${cardTempNameConfig=='default'?get.verticalStr(tempname):tempname}`; node.tempname=tempname; return node; }, connectRooms:function(list){ ui.rooms=[]; ui.roombase=ui.create.dialog(); ui.roombase.classList.add('fullwidth'); ui.roombase.classList.add('fullheight'); ui.roombase.classList.add('fixed'); ui.roombase.classList.add('scroll1'); ui.roombase.classList.add('scroll2'); ui.roombase.classList.add('noupdate'); for(var i=0;i空房间'); player.roomindex=i; player.initRoom=lib.element.Player.prototype.initRoom; player.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.connectroom); player.initRoom(list[i]); ui.rooms.push(player); } }, rarity:function(button){ var rarity=game.getRarity(button.link); if(rarity!='common'&&lib.config.show_rarity){ var intro=button.node.intro; intro.classList.add('showintro'); intro.style.fontFamily='yuanli'; intro.style.fontSize='16px'; intro.style.bottom='6px'; intro.style.left='6px'; switch(rarity){ case 'rare':intro.dataset.nature='thunderm';break; case 'epic':intro.dataset.nature='metalm';break; case 'legend':intro.dataset.nature='orangem';break; case 'junk':intro.dataset.nature='woodm';break; } intro.innerHTML=get.translation(rarity); } /*if((button.link=='xushu'||button.link=='xin_xushu'||button.link=='jsrg_guanyu')&&button.node&&button.node.name&&button.node.group){ if(button.classList.contains('newstyle')){ button.node.name.dataset.nature='watermm'; button.node.group.dataset.nature='water'; } else button.node.group.style.backgroundColor=get.translation('weiColor'); }*/ }, div:function(){ var str,innerHTML,position,position2,style,divposition,listen; for(var i=0;iposition2){ position.insertBefore(node,position.childNodes[position2]); } else{ position.appendChild(node); } } if(style) node.css(style); if(divposition) node.setPosition(divposition); if(innerHTML) node.innerHTML=innerHTML; if(listen) node.listen(listen); return node; }, filediv:function(){ var args=Array.from(arguments); var func=null; for(var i=0;iposition2){ position.insertBefore(node,position.childNodes[position2]); } else{ position.appendChild(node); } } if(style) HTMLDivElement.prototype.css.call(node,style); if(divposition) HTMLDivElement.prototype.setPosition.call(node,divposition); if(innerHTML) node.innerHTML=innerHTML; if(listen) node.onclick=listen; return node; }, iframe:function(src){ var layer=document.createElement('div'); layer.classList.add('poplayer'); layer.style.zIndex='100'; layer.listen(function(){ this.remove(); }); layer.style.background='white'; var webview=document.createElement('iframe'); webview.src=src; webview.style.width='100%'; webview.style.height='100%'; webview.style.left='0px'; webview.style.top='0px'; webview.style.position='absolute'; webview.style.border='none'; layer.appendChild(webview); var backbutton=ui.create.div('.menubutton.round','返',layer,function(){ layer.remove(); }); backbutton.style.bottom='10px'; backbutton.style.right='10px'; backbutton.style.background='rgba(0,0,0,0.4)'; backbutton.style.color='white'; backbutton.style.textShadow='rgba(0,0,0,0.5) 0px 0px 2px'; backbutton.style.boxShadow='rgba(0, 0, 0, 0.3) 0 0 0 1px, rgba(0, 0, 0, 0.3) 0 3px 10px'; backbutton.style.position='fixed'; ui.window.appendChild(layer); }, identitycircle:function(list,target){ var container=ui.create.div('.identitycircle.menubg',target); var circle=ui.create.div(container); container.dataset.num=list.length; for(var i=0;idiv').length; // node.style.top=(e.y-node.offsetHeight/2+30)+'px'; for(var i=0;iui.window.offsetHeight){ // node.style.top=(ui.winheightdow.offsetHeight-20-rect.height*1.3)/1.3+'px'; // } // if(e){ var height=node.offsetHeight; var idealtop=e.clientY/game.documentZoom; if(idealtop<10){ idealtop=10; } else if((idealtop+height)*zoom+10>ui.window.offsetHeight){ idealtop=(ui.window.offsetHeight-10)/zoom-height; } node.style.top=idealtop+'px'; node.style.left=left+'px'; // } popupContainer.classList.remove('hidden'); popupContainer.onclose=onclose; }; var clickToggle=function(){ if(this.classList.contains('disabled')) return; this.classList.toggle('on'); var config=this._link.config; if(config.onclick){ if(config.onclick.call(this,this.classList.contains('on'))===false){ this.classList.toggle('on'); } } if(config.update){ config.update(); } }; var clickSwitcher=function(){ if(this.classList.contains('disabled')) return; var node=this; this.classList.add('on'); if(this._link.menu){ var pos1=this.lastChild.getBoundingClientRect(); var pos2=ui.window.getBoundingClientRect(); if(this._link.menu.classList.contains('visual')){ openMenu(this._link.menu,{ clientX:pos1.left+pos1.width+5-pos2.left, clientY:pos1.top-pos2.top },function(){ node.classList.remove('on'); }); } else if(this._link.menu.childElementCount>10){ openMenu(this._link.menu,{ clientX:pos1.left+pos1.width+5-pos2.left, clientY:Math.min((ui.window.offsetHeight-400)/2,pos1.top-pos2.top) },function(){ node.classList.remove('on'); }); lib.setScroll(this._link.menu); } else{ openMenu(this._link.menu,{ clientX:pos1.left+pos1.width+5-pos2.left, clientY:pos1.top-pos2.top },function(){ node.classList.remove('on'); }); } } }; var clickContainer=function(){ menuContainer.classList.add('hidden'); if(connectMenu){ if(_status.enteringroom){ _status.enteringroom=false; } if(_status.creatingroom){ _status.creatingroom=false; } ui.window.classList.remove('shortcutpaused'); } else{ game.resume2(); if(game.onresume2){ game.onresume2(); } ui.arena.classList.remove('menupaused'); ui.historybar.classList.remove('menupaused'); ui.window.classList.remove('touchinfohidden'); ui.config2.classList.remove('pressdown2'); } }; var clickMenuItem=function(){ var node=this.parentNode._link; var config=node._link.config; node._link.current=this.link; var tmpName=node.lastChild.innerHTML; node.lastChild.innerHTML=config.item[this._link]; if(config.onclick){ if(config.onclick.call(node,this._link,this)===false){ node.lastChild.innerHTML=tmpName; } } if(config.update){ config.update(); } }; var createMenu=function(tabs,config){ var createPage=function(position){ var node=ui.create.div(position); lib.setScroll(ui.create.div('.left.pane',node)); lib.setScroll(ui.create.div('.right.pane',node)); return node; }; var menu=ui.create.div('.main.menu.dialog.popped.static',config.position,function(e){ e.stopPropagation(); }); if(connectMenu){ menu.classList.add('center'); menuContainer.classList.add('centermenu'); } var menuTab=ui.create.div('.menu-tab',menu); var menuTabBar=ui.create.div('.menu-tab-bar',menu); menuTabBar.style.left=(config.bar||0)+'px'; if(Math.round(2*game.documentZoom)<2){ menuTabBar.style.height='3px'; } var menuContent=ui.create.div('.menu-content',menu); var clickTab=function(){ if(this.classList.contains('disabled')) return; var active=this.parentNode.querySelector('.active'); if(active){ active.classList.remove('active'); active._link.remove(); } this.classList.add('active'); menuTabBar.style.transform='translateX('+(this.getBoundingClientRect().left-this.parentNode.firstChild.getBoundingClientRect().left)/game.documentZoom+'px)'; menuContent.appendChild(this._link); }; ui.click.menuTab=function(tab){ for(var i=0;i'+str+''); }); } } else{ node.innerHTML=''+config.name+''; if(!config.nopointer){ node.classList.add('pointerspan'); } } if(config.item){ if(typeof config.item=='function'){ config.item=config.item(); } if(Array.isArray(config.init)){ } else{ node.classList.add('switcher'); node.listen(clickSwitcher); node._link.choosing=ui.create.div('',config.item[config.init],node); node._link.menu=ui.create.div('.menu'); if(config.visualMenu){ node._link.menu.classList.add('visual'); var updateVisual=function(){ config.visualMenu(this,this._link,config.item[this._link],config); }; var createNode=function(i,before){ var visualMenu=ui.create.div(); if(config.visualBar){ if(before){ node._link.menu.insertBefore(visualMenu,before); } else{ node._link.menu.insertBefore(visualMenu,node._link.menu.lastChild); } } else{ node._link.menu.appendChild(visualMenu); } ui.create.div('.name',get.verticalStr(config.item[i]),visualMenu); visualMenu._link=i; if(config.visualMenu(visualMenu,i,config.item[i],config)!==false){ visualMenu.listen(clickMenuItem); } visualMenu.update=updateVisual; }; if(config.visualBar){ var visualBar=ui.create.div(node._link.menu,function(){ this.parentNode.parentNode.noclose=true; }); node._link.menu.classList.add('withbar'); config.visualBar(visualBar,config.item,createNode,node); visualBar.update=function(){ config.visualBar(visualBar,config.item,createNode,node); } } for(var i in config.item){ createNode(i); } lib.setScroll(node._link.menu); node._link.menu.updateBr=function(){ var br=Array.from(this.querySelectorAll('.menu.visual>br')); while(br.length){ br.shift().remove(); } var split=[]; for(var i=1;i=15) node.style.height='auto'; node.listen(clickToggle); } else if(config.input){ node.classList.add('switcher'); var input=ui.create.div(node); if(!config.fixed){ input.contentEditable=true; input.style.webkitUserSelect='text'; } input.style.minWidth='10px'; input.style.maxWidth='60%'; input.style.overflow='hidden'; input.style.whiteSpace='nowrap'; input.onkeydown=function(e){ if(e.keyCode==13){ e.preventDefault(); e.stopPropagation(); input.blur(); } }; if(config.name=='联机昵称'){ input.innerHTML=config.init||'无名玩家'; input.onblur=function(){ input.innerHTML=input.innerHTML.replace(/
        /g,''); if(!input.innerHTML||get.is.banWords(input.innerHTML)){ input.innerHTML='无名玩家'; } input.innerHTML=input.innerHTML.slice(0,12); game.saveConfig('connect_nickname',input.innerHTML); game.saveConfig('connect_nickname',input.innerHTML,'connect'); } } else if(config.name=='联机大厅'){ input.innerHTML=config.init||lib.hallURL; input.onblur=function(){ if(!input.innerHTML){ input.innerHTML=lib.hallURL; } input.innerHTML=input.innerHTML.replace(/
        /g,''); game.saveConfig('hall_ip',input.innerHTML,'connect'); } } else{ input.innerHTML=config.init; input.onblur=config.onblur; } } else{ node.classList.add('toggle'); node.listen(clickToggle); ui.create.div(ui.create.div(node)); if(config.init==true){ node.classList.add('on'); } } if(position){ position.appendChild(node); } return node; }; var updateActive,updateActiveCard; var menuUpdates=[]; menuContainer=ui.create.div('.menu-container.hidden',ui.window,clickContainer); var menux; if(!connectMenu){ ui.menuContainer=menuContainer; ui.click.configMenu=function(){ ui.click.shortcut(false) if(menuContainer.classList.contains('hidden')){ ui.config2.classList.add('pressdown2'); ui.arena.classList.add('menupaused'); ui.historybar.classList.add('menupaused'); ui.window.classList.add('touchinfohidden'); menuContainer.classList.remove('hidden'); for(var i=0;i上移↑
        下移↓
        '); move.firstChild.listen(function(){ if(node.previousSibling){ node.parentNode.insertBefore(node,node.previousSibling); var order=[]; for(var i=0;i>',page); morenodes.listen(clickmore); morenodes._onclick=clickmore; page.morenodes=morenodes; } else{ page.classList.add('expanded'); if(!connectMenu){ page.classList.add('expanded2'); } } for(var k=0;k隐藏此模式',page,function(){ if(this.firstChild.innerHTML=='隐藏此模式'){ this.firstChild.innerHTML='此模式将在重启后隐藏'; lib.config.hiddenModePack.add(mode); if(!lib.config.prompt_hidepack){ alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复'); game.saveConfig('prompt_hidepack',true); } } else{ this.firstChild.innerHTML='隐藏此模式'; lib.config.hiddenModePack.remove(mode); } game.saveConfig('hiddenModePack',lib.config.hiddenModePack); }); if(hasexpand){ hidemode.classList.add('auto-hide'); } } if(infoconfig.update){ infoconfig.update(config,map); node.update=function(){ infoconfig.update(config,map); } } } if(connectMenu){ connectDisplayMap.connect_player_number=map.connect_player_number; connectDisplayMap.connect_versus_mode=map.connect_versus_mode; updateConnectDisplayMap(); } }; if(!get.config('menu_loadondemand')) node._initLink(); return node; }; var modeorder=lib.config.modeorder||[]; for(var i in lib.mode){ modeorder.add(i); } for(var i=0;i>',page,function(){ if(autoskillexpanded){ this.classList.remove('on'); for(var k=0;k>',page,function(){ if(banskillexpanded){ this.classList.remove('on'); for(var k=0;k添加...',page,function(){ this.nextSibling.classList.toggle('hidden'); }); banskilladd.style.display='none'; banskillNodes.push(banskilladd); var banskilladdNode=ui.create.div('.config.indent.hidden.banskilladd',page); banskilladdNode.style.display='none'; banskillNodes.push(banskilladdNode); var matchBanSkill=function(skills1,skills2){ if(skills1.length!=skills2.length) return false; for(var i=0;ibb?1:-1; } return a>b?1:-1; }); var list2=[]; var skills=lib.character[list[0][0]][3]; for(var i=0;i>',page,function(){ // if(expanded){ // this.classList.remove('on'); // this.parentNode.classList.remove('expanded'); // } // else{ // this.classList.add('on'); // this.parentNode.classList.add('expanded'); // } // expanded=!expanded; // }); page.classList.add('morenodes'); for(var k=0;k>',pageboard,function(){ if(importextensionexpanded){ this.classList.remove('on'); importExtension.style.display='none'; } else{ this.classList.add('on'); importExtension.style.display=''; } importextensionexpanded=!importextensionexpanded; }); extensionnode.style.padding='13px 33px 4px'; extensionnode.style.left='0px'; importExtension=ui.create.div('.new_character.export.import',pageboard); importExtension.style.padding='0px 33px 10px'; importExtension.style.display='none'; importExtension.style.width='100%'; importExtension.style.textAlign='left'; ui.create.div('','',importExtension); var promptnode=ui.create.div('','
        ',importExtension); promptnode.style.display='none'; importExtension.firstChild.lastChild.onclick=function(){ if(promptnode.style.display!='none') return; var fileToLoad=this.previousSibling.files[0]; if(fileToLoad){ promptnode.style.display=''; promptnode.firstChild.innerHTML='正在解压...'; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent) { var data = fileLoadedEvent.target.result; var loadData=function(){ var zip=new JSZip(); zip.load(data); var images=[],audios=[],fonts=[],directories={},directoryList=[]; Object.keys(zip.files).forEach(file=>{ const parsedPath=lib.path.parse(file),directory=parsedPath.dir,fileExtension=parsedPath.ext.toLowerCase(); if(directory.startsWith('audio')&&(fileExtension=='.mp3'||fileExtension=='.ogg')) audios.push(file); else if(directory.startsWith('font')&&fileExtension=='.woff2') fonts.push(file); else if(directory.startsWith('image')&&(fileExtension=='.jpg'||fileExtension=='.png')) images.push(file); else return; if(!directories[directory]){ directories[directory]=[]; directoryList.push(directory); } directories[directory].push(parsedPath.base); }); if(audios.length||fonts.length||images.length){ var str=''; if(audios.length){ str+=audios.length+'个音频文件'; } if(fonts.length){ if(str.length) str+='、' str+=fonts.length+'个字体文件'; } if(images.length){ if(str.length) str+='、' str+=images.length+'个图片文件'; } var filelist=audios.concat(fonts).concat(images); if(filelist.length>200){ str+=',导入时间可能较长'; } var assetLoaded=function(){ promptnode.firstChild.innerHTML='导入成功。重新启动×'; promptnode.firstChild.querySelectorAll('span')[0].onclick=game.reload; promptnode.firstChild.querySelectorAll('span')[1].onclick=function(){ promptnode.style.display='none'; } }; if(confirm('本次将导入'+str+',是否继续?')){ promptnode.firstChild.innerHTML='正在导入... 详细信息'; promptnode.firstChild.querySelector('span.hrefnode').onclick=ui.click.consoleMenu; if(lib.node&&lib.node.fs){ var writeFile=function(){ if(filelist.length){ var str=filelist.shift(); game.print(str.slice(str.lastIndexOf('/')+1)); lib.node.fs.writeFile(__dirname+'/'+str,zip.files[str].asNodeBuffer(),null,writeFile); } else{ assetLoaded(); } }; game.ensureDirectory(directoryList,writeFile); } else{ var getDirectory=function(){ if(directoryList.length){ var dir=directoryList.shift(); var filelist=directories[dir]; window.resolveLocalFileSystemURL(lib.assetURL+dir,function(entry){ var writeFile=function(){ if(filelist.length){ var filename=filelist.shift(); game.print(filename); entry.getFile(filename,{create:true},function(fileEntry){ fileEntry.createWriter(function(fileWriter){ fileWriter.onwriteend=writeFile; fileWriter.onerror = function(e) { game.print('Write failed: ' + e.toString()); }; fileWriter.write(zip.files[dir+'/'+filename].asArrayBuffer()); }); }); } else{ getDirectory(); } }; writeFile(); }); } else{ assetLoaded(); } }; game.ensureDirectory(directoryList,getDirectory); } } else{ promptnode.style.display='none'; } } else{ alert('没有检测到素材'); } } if(!window.JSZip){ lib.init.js(lib.assetURL+'game','jszip',loadData); } else{ loadData(); } }; fileReader.readAsArrayBuffer(fileToLoad, "UTF-8"); } } var dashboard=ui.create.div(pageboard); var clickDash=function(){ ui.create.templayer(); pageboard.hide(); this.link.show(); if(this.link.init){ this.link.init(); } }; var createDash=function(str1,str2,node){ var dash=ui.create.div('.menubutton.large.dashboard'); dashboard.appendChild(dash); page.appendChild(node); dash.link=node; node.link=dash; dash.listen(clickDash); lib.setScroll(node); ui.create.div('',str1,dash); ui.create.div('',str2,dash); }; var createDash2=function(str1,str2,path,page){ var dash=ui.create.div('.menubutton.large.dashboard.dashboard2'); page.appendChild(dash); dash.listen(function(){ page.path=path; enterDirectory(page,path); }); ui.create.div('',str1,dash); ui.create.div('',str2,dash); }; var removeFile=function(selected,page){ if(lib.node&&lib.node.fs){ var unlink=function(){ if(selected.length){ lib.node.fs.unlink(__dirname+'/'+selected.shift().path,unlink); } else{ enterDirectory(page,page.currentpath); } } unlink(); } else{ window.resolveLocalFileSystemURL(lib.assetURL+page.currentpath,function(entry){ var unlink=function(){ if(selected.length){ entry.getFile(selected.shift().filename,{create:false},function(fileEntry){ fileEntry.remove(unlink); }); } else{ enterDirectory(page,page.currentpath); } } unlink(); }); } }; var clickDirectory=function(){ if(_status.dragged) return; var page=this.parentNode.parentNode.parentNode; if(page.deletebutton.classList.contains('active')){ if(confirm('确认删除'+this.innerHTML+'文件夹?(此操作不可撤销)')){ if(lib.node&&lib.node.fs){ try{ var removeDirectory=function(path,callback){ lib.node.fs.readdir(__dirname+'/'+path,function(err,list){ if(err){ console.log(err); return; } var removeFile=function(){ if(list.length){ var filename=list.shift(); var url=__dirname+'/'+path+'/'+filename; if(lib.node.fs.statSync(url).isDirectory()){ removeDirectory(path+'/'+filename,removeFile); } else{ lib.node.fs.unlink(url,removeFile); } } else{ lib.node.fs.rmdir(__dirname+'/'+path,callback); } } removeFile(); }); }; removeDirectory(this.path,function(){ enterDirectory(page,page.currentpath); }); } catch(e){ console.log(e); } } else{ window.resolveLocalFileSystemURL(lib.assetURL+this.path,function(entry){ entry.removeRecursively(function(){ enterDirectory(page,page.currentpath); }); }); } } return; } enterDirectory(page,this.path); }; var clickFile=function(){ if(_status.dragged) return; var page=this.parentNode.parentNode.parentNode; if(page.deletebutton.classList.contains('active')){ if(confirm('确认删除'+this.innerHTML+'?(此操作不可撤销)')){ removeFile([this],page); } return; } this.classList.toggle('thundertext'); page.clicked=true; if(this.ext=='jpg'||this.ext=='png'){ if(this.classList.contains('thundertext')){ if(!this.previewnode){ this.previewnode=document.createElement('img'); this.previewnode.src=lib.assetURL+this.path; this.previewnode.width='60'; this.previewnode.style.maxHeight='120px'; this.parentNode.appendChild(this.previewnode); } } else{ if(this.previewnode){ this.previewnode.remove(); delete this.previewnode; } } } else if(this.ext=='mp3'||this.ext=='ogg'){ if(this.classList.contains('thundertext')){ if(!this.previewnode){ this.previewnode=game.playAudio(this.path.slice(6)); } } else{ if(this.previewnode){ this.previewnode.remove(); delete this.previewnode; } } } }; var clickFileList=function(){ if(!this.parentNode) return; if(this.parentNode.clicked){ this.parentNode.clicked=false; } else{ var selected=Array.from(this.querySelectorAll('span.thundertext')); for(var i=0;ib) return 1; if(a'+folders[i],filelist); entry.firstChild.addEventListener(lib.config.touchscreen?'touchend':'click',clickDirectory); entry.firstChild.path=parent+folders[i] } for(var i=0;i'+files[i],filelist); entry.firstChild.addEventListener(lib.config.touchscreen?'touchend':'click',clickFile); entry.firstChild.ext=files[i].slice(files[i].lastIndexOf('.')+1); entry.firstChild.path=parent+files[i]; entry.firstChild.filename=files[i]; } }); }; var dash1=(function(){ var page=ui.create.div('.hidden.menu-buttons'); page.reset=function(){ page.innerHTML=''; var backbutton=ui.create.div('.menubutton.round','返',page,function(){ ui.create.templayer(); page.hide(); pageboard.show(); }); backbutton.style.zIndex=1; backbutton.style.right='10px'; backbutton.style.bottom='15px'; var placeholder=ui.create.div('.placeholder',page); placeholder.style.position='relative'; placeholder.style.display='block'; placeholder.style.width='100%'; placeholder.style.height='14px'; createDash2('将','武将图片','image/character',page); createDash2('肤','皮肤图片','image/skin',page); createDash2('卡','卡牌图片','image/card',page); createDash2('模','模式图片','image/mode',page); createDash2('始','开始图片','image/splash',page); createDash2('景','背景图片','image/background',page); }; page.reset(); return page; }()); var dash2=(function(){ var page=ui.create.div('.hidden.menu-buttons'); page.reset=function(){ page.innerHTML=''; var backbutton=ui.create.div('.menubutton.round','返',page,function(){ ui.create.templayer(); page.hide(); pageboard.show(); }); backbutton.style.zIndex=1; backbutton.style.right='10px'; backbutton.style.bottom='15px'; var placeholder=ui.create.div('.placeholder',page); placeholder.style.position='relative'; placeholder.style.display='block'; placeholder.style.width='100%'; placeholder.style.height='14px'; createDash2('技','技能配音','audio/skill',page); createDash2('卡','男性卡牌','audio/card/male',page); createDash2('牌','女性卡牌','audio/card/female',page); createDash2('亡','阵亡配音','audio/die',page); createDash2('效','游戏音效','audio/effect',page); createDash2('景','背景音乐','audio/background',page); }; page.reset(); return page; }()); var dash3=(function(){ var page=ui.create.div('.hidden.menu-buttons'); page.path='font'; page.reset=function(){ ui.create.templayer(); page.hide(); pageboard.show(); }; page.init=function(){ enterDirectory(page,'font'); }; return page; }()); var dash4=(function(){ var page=ui.create.div('.hidden.menu-buttons'); page.path=''; page.reset=function(){ ui.create.templayer(); page.hide(); pageboard.show(); }; page.init=function(){ enterDirectory(page,''); }; return page; }()); createDash('图','图片文件',dash1); createDash('音','音频文件',dash2); createDash('字','字体文件',dash3); createDash('全','全部文件',dash4); }; if(!get.config('menu_loadondemand')) node._initLink(); }()); createModeConfig('others',start.firstChild); var active=start.firstChild.querySelector('.active'); if(!active){ active=start.firstChild.firstChild; active.classList.add('active'); } if(!active.link) active._initLink(); rightPane.appendChild(active.link); }()); (function(){ var start=menuxpages.shift(); var rightPane=start.lastChild; var clickMode=function(){ var active=this.parentNode.querySelector('.active'); if(active){ if(active===this){ return; } active.classList.remove('active'); active.link.remove(); } this.classList.add('active'); updateActive(this); if(this.link) rightPane.appendChild(this.link); else{ this._initLink(); rightPane.appendChild(this.link); } }; updateActive=function(node){ if(!node){ node=start.firstChild.querySelector('.active'); if(!node){ return; } } if (!node.link) { node._initLink(); } for(var i=0;i=5){ node.classList.add('smallfont'); } if(position2){ position.insertBefore(node,position2); } node.mode=mode; node._initLink=function(){ node.link=page; page.node=node; var list=[]; var boolAI=true; var alterableSkills=[]; var alterableCharacters=[]; var charactersToAlter=[]; for(var i in _info){ if(_info[i][4]&&_info[i][4].contains('unseen')) continue; if(connectMenu&&lib.connectBanned.contains(i)) continue; list.push(i); if(boolAI&&!lib.config.forbidai_user.contains(i)) boolAI=false; for(var j=0;j<_info[i][3].length;j++){ if(!lib.skill[_info[i][3][j]]){ continue; } if(lib.skill[_info[i][3][j]].alter){ alterableSkills.add(_info[i][3][j]); alterableCharacters.add(i); if(lib.config.vintageSkills.contains(_info[i][3][j])){ charactersToAlter.add(i); } } } } alterableCharacters.sort(); list.sort(lib.sort.character); var list2=list.slice(0); var cfgnode=createConfig({ name:'开启', _name:mode, init:lib.config.characters.contains(mode), onclick:togglePack }); var cfgnodeAI=createConfig({ name:'仅点将可用', _name:mode, init:boolAI, intro:'将该武将包内的武将全部设置为仅点将可用', onclick:function(bool){ if(bool){ for(var i=0;i该武将包不可被隐藏',page); } else if(!mode.startsWith('mode_')){ ui.create.div('.config.pointerspan','隐藏武将包',page,function(){ if(this.firstChild.innerHTML=='隐藏武将包'){ if(confirm('真的要隐藏“'+get.translation(mode+'_character_config')+'”武将包吗?\n建议使用“关闭”而不是“隐藏”功能,否则将会影响其他相关武将包的正常运行!')){ this.firstChild.innerHTML='武将包将在重启后隐藏'; lib.config.hiddenCharacterPack.add(mode); if(!lib.config.prompt_hidepack){ alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复'); game.saveConfig('prompt_hidepack',true); } } } else{ this.firstChild.innerHTML='隐藏武将包'; lib.config.hiddenCharacterPack.remove(mode); } game.saveConfig('hiddenCharacterPack',lib.config.hiddenCharacterPack); }); } } }; if(!get.config('menu_loadondemand')) node._initLink(); return node; }; if(lib.config.show_favourite_menu&&!connectMenu&&Array.isArray(lib.config.favouriteCharacter)){ lib.characterPack.mode_favourite={}; for(var i=0;i{ if(key.startsWith('mode_')) createModeConfig(key,start.firstChild); }); var active=start.firstChild.querySelector('.active'); if(!active){ active=start.firstChild.firstChild; if(active.style.display=='none'){ active=active.nextSibling; if(active.style.display=='none'){ active=active.nextSibling; } } active.classList.add('active'); updateActive(active); } if(!active.link) active._initLink(); rightPane.appendChild(active.link); if(!connectMenu){ var node1=ui.create.div('.lefttext','全部开启',start.firstChild,function(){ game.saveConfig('characters',lib.config.all.characters); updateNodes(); }); var node2=ui.create.div('.lefttext','恢复默认',start.firstChild,function(){ game.saveConfig('characters',lib.config.defaultcharacters); updateNodes(); }); node1.style.marginTop='12px'; node2.style.marginTop='7px'; } updateNodes(); }()); (function(){ var start=menuxpages.shift(); var rightPane=start.lastChild; var pileCreated=false; var recreatePile=function(){ lib.config.customcardpile['当前牌堆']=[lib.config.bannedpile,lib.config.addedpile]; game.saveConfig('customcardpile',lib.config.customcardpile); game.saveConfig('cardpilename','当前牌堆',true); pileCreated=false; }; var clickMode=function(){ var active=this.parentNode.querySelector('.active'); if(active===this){ return; } active.classList.remove('active'); active.link.remove(); active=this; this.classList.add('active'); updateActiveCard(this); if(this.mode=='cardpile'){ this.create(); } if(this.link) rightPane.appendChild(this.link); else{ this._initLink(); rightPane.appendChild(this.link); } }; updateActiveCard=function(node){ if(!node){ node=start.firstChild.querySelector('.active'); if(!node){ return; } } if(!node.link) node._initLink(); for(var i=0;i=5){ node.classList.add('smallfont'); } node.mode=mode; node._initLink=function(){ node.link=page; var list=[]; for(var i=0;isort2){ return 1; } else{ return -1; } }); var cfgnode=createConfig({ name:'开启', _name:mode, init:lib.config.cards.contains(mode), onclick:togglePack }); if(!mode.startsWith('mode_')){ page.appendChild(cfgnode); } else{ page.style.paddingTop='8px'; } var banCard=function(e){ if(_status.clicked){ _status.clicked=false; return; } if(mode.startsWith('mode_')&&!mode.startsWith('mode_extension_')&&mode!='mode_banned'){ return; } ui.click.touchpop(); this._banning=connectMenu?'online':'offline'; ui.click.intro.call(this,e); _status.clicked=false; delete this._banning; }; var updateBanned=function(){ var list; if(connectMenu){ var mode=menux.pages[0].firstChild.querySelector('.active'); if(mode&&mode.mode){ list=lib.config['connect_'+mode.mode+'_bannedcards']; } } else{ list=lib.config[get.mode()+'_bannedcards']; } if(list&&list.contains(this.link[2])){ this.classList.add('banned'); } else{ this.classList.remove('banned'); } }; var buttons=ui.create.buttons(list,'vcard',page); for(var i=0;i隐藏卡牌包',page,function(){ if(this.firstChild.innerHTML=='隐藏卡牌包'){ this.firstChild.innerHTML='卡牌包将在重启后隐藏'; lib.config.hiddenCardPack.add(mode); if(!lib.config.prompt_hidepack){ alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复'); game.saveConfig('prompt_hidepack',true); } } else{ this.firstChild.innerHTML='隐藏卡牌包'; lib.config.hiddenCardPack.remove(mode); } game.saveConfig('hiddenCardPack',lib.config.hiddenCardPack); }); } if(!mode.startsWith('mode_')&&lib.cardPile[mode]){ var cardpileNodes=[]; var cardpileexpanded=false; if(!lib.config.bannedpile[mode]){ lib.config.bannedpile[mode]=[]; } if(!lib.config.addedpile[mode]){ lib.config.addedpile[mode]=[]; } ui.create.div('.config.more.pile','编辑牌堆
        >
        ',page,function(){ if(cardpileexpanded){ this.classList.remove('on'); for(var k=0;k{ if(key.startsWith('mode_')) createModeConfig(key,start.firstChild); }); var active=start.firstChild.querySelector('.active'); if(!active){ active=start.firstChild.firstChild; if(active.style.display=='none'){ active=active.nextSibling; } active.classList.add('active'); updateActiveCard(active); } if(!active.link) active._initLink(); rightPane.appendChild(active.link); (function(){ if(connectMenu) return; var page=ui.create.div('.menu-buttons'); var node=ui.create.div('.menubutton.large','牌堆',clickMode); start.firstChild.insertBefore(node,start.firstChild.querySelector('.lefttext')); node.link=page; node.mode='cardpile'; node.create=function(){ if(pileCreated) return; pileCreated=true; page.innerHTML=''; var pileList=null; var createList=function(){ if(pileList){ pileList.remove(); } var list=['默认牌堆']; if(lib.config.customcardpile['当前牌堆']){ list.push('当前牌堆'); } for(var i in lib.config.customcardpile){ list.add(i); } var currentpile=get.config('cardpilename'); if(!currentpile){ if(list.contains('当前牌堆')){ currentpile='当前牌堆'; } else{ currentpile='默认牌堆'; } } pileList=ui.create.selectlist(list,currentpile,pileChoose,function(e){ game.saveConfig('cardpilename',this.value,true); restart.style.display=''; }); pileList.style.float='right'; } var pileChoose=ui.create.div('.config.toggle.cardpilecfg.nomarginleft','选择牌堆',page); createList(); var pileDel=function(){ delete lib.config.customcardpile[this.parentNode.link]; this.parentNode.remove(); game.saveConfig('customcardpile',lib.config.customcardpile); for(var i in lib.config.mode_config){ if(i=='global') continue; if(lib.config.mode_config[i].cardpilename==this.parentNode.link){ game.saveConfig('cardpilename',null,i); } } createList(); }; var restart=ui.create.div('.config.more','重新启动',game.reload,page); restart.style.display='none'; var createPileNode=function(name){ var node=ui.create.div('.config.toggle.cardpilecfg.nomarginleft',name); node.link=name; var del=document.createElement('span'); del.innerHTML='删除'; del.classList.add('cardpiledelete'); del.onclick=pileDel; node.appendChild(del); if(name=='当前牌堆'){ page.insertBefore(node,pileChoose.nextSibling); } else{ page.insertBefore(node,restart); } }; for(var i in lib.config.customcardpile){ createPileNode(i); } var exportCardPile; ui.create.div('.config.more','保存当前牌堆
        >
        ',page,function(){ this.classList.toggle('on'); if(this.classList.contains('on')){ exportCardPile.classList.remove('hidden'); } else{ exportCardPile.classList.add('hidden'); } }); exportCardPile=ui.create.div('.config.cardpileadd.indent',page); exportCardPile.classList.add('hidden'); ui.create.div('','名称:',exportCardPile); var input=exportCardPile.firstChild.lastChild.previousSibling; input.value='自定义牌堆'; input.style.marginRight='3px'; input.style.width='120px'; exportCardPile.firstChild.lastChild.onclick=function(){ var name=input.value; var ok=true; if(lib.config.customcardpile[name]||name=='默认牌堆'||name=='当前牌堆'){ for(var i=1;i<=1000;i++){ if(!lib.config.customcardpile[name+'('+i+')']){ name=name+'('+i+')'; break; } } } lib.config.customcardpile[name]=[lib.config.bannedpile,lib.config.addedpile]; delete lib.config.customcardpile['当前牌堆']; for(var i in lib.mode){ if(lib.config.mode_config[i]&& (lib.config.mode_config[i].cardpilename=='当前牌堆'||!lib.config.mode_config[i].cardpilename)){ game.saveConfig('cardpilename',name,i); } } for(var i=0;i=5){ node.classList.add('smallfont'); } node.mode=mode; // node._initLink=function(){ node.link=page; for(var i in lib.extensionMenu[mode]){ if(i=='game') continue; var cfg=copyObj(lib.extensionMenu[mode][i]); var j; if(mode.startsWith('extension_')){ j=mode+'_'+i; } else{ j=mode+'_'+i+'_playpackconfig'; } cfg._name=j; if(!lib.config.hasOwnProperty(j)){ game.saveConfig(j,cfg.init); } else{ cfg.init=lib.config[j]; } if(i=='enable'){ cfg.onclick=togglePack; } else if(!lib.extensionMenu[mode][i].onclick){ cfg.onclick=function(result){ var cfg=this._link.config; game.saveConfig(cfg._name,result); }; } var cfgnode=createConfig(cfg); if(cfg.onswitch){ cfgnode.onswitch=cfg.onswitch; } page.appendChild(cfgnode); } // }; // if(!get.config('menu_loadondemand')) node._initLink(); return node; }; for(var i in lib.extensionMenu){ if(lib.config.all.stockextension.contains(i)&&!lib.config.all.plays.contains(i)) continue; if(lib.config.hiddenPlayPack.contains(i)) continue; createModeConfig(i,start.firstChild); } (function(){ if(!lib.device&&!lib.db) return; if(lib.config.show_extensionmaker==false) return; var page=ui.create.div('#create-extension'); var node=ui.create.div('.menubutton.large','制作扩展',start.firstChild,clickMode); node.mode='create'; game.editExtension=function(name){ node._initLink(); game.editExtension(name); }; node._initLink=function(){ node.link=page; var pageboard=ui.create.div(page); var inputExtLine=ui.create.div(pageboard); inputExtLine.style.transition='all 0s'; inputExtLine.style.padding='10px'; inputExtLine.style.height='22px'; inputExtLine.style.lineHeight='22px'; inputExtLine.style.whiteSpace='nowrap'; inputExtLine.style.overflow='visible'; var inputExtSpan=document.createElement('span'); inputExtSpan.innerHTML='扩展名:'; inputExtLine.appendChild(inputExtSpan); var inputExtName=document.createElement('input'); inputExtName.type='text'; inputExtName.value='无名扩展'; inputExtName.style.width='80px'; inputExtName.style.textAlign='center'; inputExtLine.appendChild(inputExtName); var buttonConfirmOnclick=function(){ buttonConfirm.style.display='none'; inputExtSpan.style.display='none'; inputExtName.style.display='none'; authorExtLine.style.display='none'; introExtLine.style.display='none'; forumExtLine.style.display='none'; diskExtLine.style.display='none'; versionExtLine.style.display='none'; okExtLine.style.display='none'; inputExtLine.style.padding='10px'; buttonRename.style.display=''; buttonSave.style.display=''; buttonReset.style.display=''; buttonExport.style.display=''; inputExtSpan.innerHTML='扩展名称:'; inputExtName.style.width='100px'; inputExtName.style.textAlign=''; dashboard.style.display=''; }; var createExtLine=function(str,str2){ var infoExtLine=ui.create.div(pageboard); infoExtLine.style.display='none'; infoExtLine.style.padding='0 10px 10px 10px'; infoExtLine.style.height='22px'; infoExtLine.style.lineHeight='22px'; infoExtLine.style.whiteSpace='nowrap'; infoExtLine.style.overflow='visible'; if(typeof str=='boolean'){ var inputConfirm=document.createElement('button'); inputConfirm.innerHTML='确定'; inputConfirm.onclick=buttonConfirmOnclick; infoExtLine.appendChild(inputConfirm); return infoExtLine; } var infoExtSpan=document.createElement('span'); infoExtSpan.innerHTML=str+':'; infoExtLine.appendChild(infoExtSpan); var infoExtName=document.createElement('input'); infoExtName.type='text'; infoExtName.style.width='100px'; infoExtName.value=str2||''; infoExtLine.appendChild(infoExtName); return infoExtLine; }; var authorExtLine=createExtLine('扩展作者',get.connectNickname()); var introExtLine=createExtLine('扩展描述'); var versionExtLine=createExtLine('扩展版本','1.0'); var diskExtLine=createExtLine('网盘地址'); var forumExtLine=createExtLine('讨论地址'); var okExtLine=createExtLine(true); game.editExtension=function(name){ page.currentExtension=name||'无名扩展'; inputExtName.value=page.currentExtension; if(name&&lib.extensionPack[name]){ authorExtLine.querySelector('input').value=lib.extensionPack[name].author||''; introExtLine.querySelector('input').value=lib.extensionPack[name].intro||''; diskExtLine.querySelector('input').value=lib.extensionPack[name].diskURL||''; forumExtLine.querySelector('input').value=lib.extensionPack[name].forumURL||''; versionExtLine.querySelector('input').value=lib.extensionPack[name].version||''; } else{ authorExtLine.querySelector('input').value=get.connectNickname()||''; introExtLine.querySelector('input').value=''; diskExtLine.querySelector('input').value=''; forumExtLine.querySelector('input').value=''; versionExtLine.querySelector('input').value='1.0'; } if(name){ inputExtName.disabled=true; buttonConfirm.style.display='none'; inputExtSpan.style.display='none'; inputExtName.style.display='none'; buttonRename.style.display=''; buttonSave.style.display=''; buttonReset.style.display=''; buttonExport.style.display=''; } else{ inputExtName.disabled=false; buttonConfirm.style.display=''; inputExtSpan.innerHTML='扩展名:'; inputExtName.style.width='80px'; inputExtName.style.textAlign='center'; inputExtSpan.style.display=''; inputExtName.style.display=''; buttonRename.style.display='none'; buttonSave.style.display='none'; buttonReset.style.display='none'; buttonExport.style.display='none'; } dashboard.style.display=''; exportExtLine.style.display='none'; shareExtLine.style.display='none'; authorExtLine.style.display='none'; introExtLine.style.display='none'; forumExtLine.style.display='none'; diskExtLine.style.display='none'; versionExtLine.style.display='none'; okExtLine.style.display='none'; inputExtLine.style.padding='10px'; dash1.reset(name); dash2.reset(name); dash3.reset(name); dash4.reset(name); dash1.link.classList.remove('active'); dash2.link.classList.remove('active'); dash3.link.classList.remove('active'); dash4.link.classList.remove('active'); var active=node.parentNode.querySelector('.active'); if(active===node){ return; } active.classList.remove('active'); active.link.remove(); node.classList.add('active'); rightPane.appendChild(node.link); } var processExtension=function(exportext){ if(page.currentExtension){ if(page.currentExtension!=inputExtName.value&&!exportext){ game.removeExtension(page.currentExtension); } } inputExtName.disabled=true; setTimeout(function(){ var ext={}; var config=null,help=null; for(var i in dash4.content){ try{ if(i=='content'||i=='precontent'){ eval('ext[i]='+dash4.content[i]); if(typeof ext[i]!='function'){ throw('err'); } else{ ext[i]=ext[i].toString(); } } else{ eval(dash4.content[i]); eval('ext[i]='+i); if(ext[i]==null||typeof ext[i]!='object'){ throw('err'); } else{ ext[i]=JSON.stringify(ext[i]); } } } catch(e){ console.log(e); delete ext[i]; } } page.currentExtension=inputExtName.value||'无名扩展'; var str='{name:"'+page.currentExtension+'"'; for(var i in ext){ str+=','+i+':'+ext[i]; } dash2.content.pack.list=[]; for(var i=0;i{ var character=pack.character; for (var key in character){ var info=character[key]; if(Array.isArray(info[4])){ var tag=info[4].find(tag=>/^die:.+$/.test(tag)); if(tag){ info[4].remove(tag); if(typeof game.readFile=='function'){ info[4].push('die:ext:'+page.currentExtension+'/audio/die/'+tag.slice(tag.lastIndexOf('/')+1)); }else{ info[4].push('die:db:extension-'+page.currentExtension+':audio/die/'+tag.slice(tag.lastIndexOf('/')+1)); } } } } return pack; })(dash1.content.pack), card:dash2.content.pack, skill:dash3.content.pack, intro:introExtLine.querySelector('input').value||'', author:authorExtLine.querySelector('input').value||'', diskURL:diskExtLine.querySelector('input').value||'', forumURL:forumExtLine.querySelector('input').value||'', version:versionExtLine.querySelector('input').value||'', }); var files={character:[],card:[],skill:[],audio:[]}; for(var i in dash1.content.image){ files.character.push(i); } for(var i in dash1.content.audio){ files.audio.push('audio/die/'+i); } for(var i in dash2.content.image){ files.card.push(i); } for(var i in dash3.content.audio){ files.skill.push(i); } str+=',files:'+JSON.stringify(files); str+='}'; var extension={'extension.js':'game.import("extension",function(lib,game,ui,get,ai,_status){return '+str+'})'}; for(var i in dash1.content.image){ extension[i]=dash1.content.image[i]; } for(var i in dash1.content.audio){ extension['audio/die/'+i]=dash1.content.audio[i]; } for(var i in dash2.content.image){ extension[i]=dash2.content.image[i]; } game.readFile('LICENSE',function(data){ extension['LICENSE']=data; game.writeFile(data,'extension/'+page.currentExtension,'LICENSE',function(){}) if(exportext){ var proexport=function(){ game.importExtension(extension,null,page.currentExtension,{ intro:introExtLine.querySelector('input').value||'', author:authorExtLine.querySelector('input').value||'', netdisk:diskExtLine.querySelector('input').value||'', forum:forumExtLine.querySelector('input').value||'', version:versionExtLine.querySelector('input').value||'', }); }; if(game.getFileList){ game.getFileList('extension/'+page.currentExtension,function(folders,files){ extension._filelist=files; proexport(); }); } else{ proexport(); } } else{ game.importExtension(extension,function(){ exportExtLine.style.display=''; }); } },function(){ alert('许可证文件丢失,无法导出扩展'); }); },500); }; var buttonConfirm=document.createElement('button'); buttonConfirm.innerHTML='确定'; buttonConfirm.style.marginLeft='5px'; buttonConfirm.onclick=buttonConfirmOnclick; inputExtLine.appendChild(buttonConfirm); var buttonRename=document.createElement('button'); buttonRename.innerHTML='选项'; buttonRename.style.marginLeft='2px'; buttonRename.style.marginRight='2px'; buttonRename.style.display='none'; buttonRename.onclick=function(){ inputExtSpan.style.display=''; inputExtName.style.display=''; authorExtLine.style.display=''; introExtLine.style.display=''; forumExtLine.style.display=''; diskExtLine.style.display=''; versionExtLine.style.display=''; okExtLine.style.display='block'; inputExtLine.style.padding='20px 10px 10px 10px'; inputExtName.disabled=false; buttonRename.style.display='none'; buttonSave.style.display='none'; buttonReset.style.display='none'; buttonExport.style.display='none'; inputExtSpan.innerHTML='扩展名称:'; inputExtName.style.width='100px'; inputExtName.style.textAlign=''; dashboard.style.display='none'; }; inputExtLine.appendChild(buttonRename); var buttonReset=document.createElement('button'); buttonReset.innerHTML='重置'; buttonReset.style.marginLeft='2px'; buttonReset.style.marginRight='2px'; buttonReset.style.display='none'; buttonReset.onclick=function(){ if(confirm('当前扩展将被清除,是否确定?')){ game.editExtension(); } }; inputExtLine.appendChild(buttonReset); var buttonSave=document.createElement('button'); buttonSave.innerHTML='保存'; buttonSave.style.marginLeft='2px'; buttonSave.style.marginRight='2px'; buttonSave.style.display='none'; buttonSave.onclick=function(){ dash1.link.classList.remove('active'); dash2.link.classList.remove('active'); dash3.link.classList.remove('active'); dash4.link.classList.remove('active'); processExtension(); }; inputExtLine.appendChild(buttonSave); var buttonExport=document.createElement('button'); buttonExport.innerHTML='导出'; buttonExport.style.marginLeft='2px'; buttonExport.style.marginRight='2px'; buttonExport.style.display='none'; buttonExport.onclick=function(){ function oldExport(){ processExtension(true); if(lib.config.show_extensionshare){ shareExtLine.style.display=''; } } if(typeof game.readFile=='function'&& window.noname_shijianInterfaces&& typeof window.noname_shijianInterfaces.shareExtensionWithPassWordAsync=='function'&& confirm('是否使用诗笺版自带的导出功能来导出扩展?')){ const extName=inputExtName.value; if (!extName) { alert('未检测到扩展名,将使用无名杀自带的导出功能'); oldExport(); return; } game.readFile(`extension/${extName}/extension.js`, () => { const pwd=prompt("请输入压缩包密码,不设密码直接点确定"); let result; if(pwd===''||pwd=== null){ window.noname_shijianInterfaces.shareExtensionAsync(extName); }else{ window.noname_shijianInterfaces.shareExtensionWithPassWordAsync(extName, pwd); } },()=>{ alert('未检测到扩展文件,将使用无名杀自带的导出功能'); oldExport(); }); }else{ oldExport(); } }; inputExtLine.appendChild(buttonExport); var exportExtLine=ui.create.div(pageboard); exportExtLine.style.display='none'; exportExtLine.style.width='calc(100% - 40px)'; exportExtLine.style.textAlign='left'; exportExtLine.style.marginBottom='5px'; if(lib.device=='ios'){ exportExtLine.innerHTML='已保存。退出游戏并重新打开后生效×'; exportExtLine.querySelectorAll('span')[0].onclick=function(){ exportExtLine.style.display='none'; }; } else{ exportExtLine.innerHTML='重启后生效。立即重启×'; exportExtLine.querySelectorAll('span')[0].onclick=game.reload; exportExtLine.querySelectorAll('span')[1].onclick=function(){ exportExtLine.style.display='none'; }; } var shareExtLine=ui.create.div(pageboard); shareExtLine.style.display='none'; shareExtLine.style.width='calc(100% - 40px)'; shareExtLine.style.textAlign='left'; shareExtLine.style.marginBottom='5px'; shareExtLine.innerHTML='已导出扩展。分享扩展×'; shareExtLine.querySelectorAll('span')[0].onclick = function () { //这个链接404了 //game.open('https://tieba.baidu.com/p/5439380222'); //无名杀贴吧首页 game.open('https://tieba.baidu.com/f?ie=utf-8&kw=%E6%97%A0%E5%90%8D%E6%9D%80'); }; shareExtLine.querySelectorAll('span')[1].onclick=function(){ shareExtLine.style.display='none'; }; var dashboard=ui.create.div(pageboard); var clickDash=function(){ ui.create.templayer(); pageboard.hide(); this.link.show(); if(this.link.init){ this.link.init(); } }; var createDash=function(str1,str2,node){ var dash=ui.create.div('.menubutton.large.dashboard'); dashboard.appendChild(dash); page.appendChild(node); dash.link=node; node.link=dash; dash.listen(clickDash); lib.setScroll(node); ui.create.div('',str1,dash); ui.create.div('',str2,dash); }; var dash1=(function(){ var page=ui.create.div('.hidden.menu-buttons'); var currentButton=null; page.init=function(){ if(!page.querySelector('.button.character')){ toggle.classList.add('on'); newCharacter.style.display=''; } }; var updateButton=function(){ var name=page.querySelector('input.new_name').value; if(!name){ editnode.classList.add('disabled'); return; } name=name.split('|'); name=name[0]; if(currentButton){ if(currentButton.link!=name){ if(lib.character[name]||page.content.pack.character[name]){ editnode.classList.add('disabled'); return; } } } else{ if(lib.character[name]||page.content.pack.character[name]){ editnode.classList.add('disabled'); return; } } if(!fakeme.image){ if(!page.content.image[name+'.jpg']){ editnode.classList.add('disabled'); return; } } editnode.classList.remove('disabled'); }; var clickButton=lib.gnc.of(function*(){ if(currentButton==this){ resetEditor(); return; } resetEditor(); currentButton=this; toggle.classList.add('on'); newCharacter.style.display=''; fakeme.classList.add('inited'); fakeme.style.backgroundImage=this.style.backgroundImage; if(page.content.pack.translate[this.link]!=this.link){ newCharacter.querySelector('.new_name').value=this.link+'|'+page.content.pack.translate[this.link]; } else{ newCharacter.querySelector('.new_name').value=this.link; } var info=page.content.pack.character[this.link]; newCharacter.querySelector('.new_hp').value=info[2]; sexes.value=info[0]; groups.value=info[1]; if(info[4]){ for(var i=0;i{ if(typeof game.readFile=='function'){ game.readFile(info[4][i].slice(4).replace('ext:','extension/'),arraybuffer=>{ dieaudionode.arrayBuffer=arraybuffer; resolve(); },()=>{ console.warn(`未找到${info[4][i].slice(4).replace('ext:','extension/')}阵亡配音`); resolve(); }); }else{ game.getDB('image',info[4][i].slice(7)).then(octetStream=>{ dieaudionode.arrayBuffer=octetStream; resolve(); },()=>{ console.warn(`未找到${info[4][i].slice(4)}阵亡配音`); resolve(); }); } }); } } } var skills=info[3]; for(var i=0;i{ createButton(i,value); loadImage(file,value); }); } } else{ page.content={ pack:{ character:{}, translate:{} }, image:{}, audio:{} }; toggle.classList.add('on'); newCharacter.style.display=''; } }; ui.create.div('.config.more','
        返回',page,function(){ ui.create.templayer(); page.hide(); pageboard.show(); }); page.content={ pack:{ character:{}, translate:{} }, image:{}, audio:{} }; var newCharacter; var toggle=ui.create.div('.config.more.on','创建武将
        >
        ',page,function(){ this.classList.toggle('on'); if(this.classList.contains('on')){ newCharacter.style.display=''; } else{ newCharacter.style.display='none'; } }); var resetEditor=function(){ currentButton=null; toggle.classList.remove('on'); newCharacter.style.display='none'; fakeme.classList.remove('inited'); delete fakeme.image; delete fakeme.image64; fakeme.style.backgroundImage=''; var inputs=newCharacter.querySelectorAll('input'); for(var i=0;i',newCharacter).style.paddingTop='8px'; ui.create.div('.indent','介绍:',newCharacter).style.paddingTop='8px'; ui.create.div('.indent','体力:',newCharacter).style.paddingTop='8px'; newCharacter.querySelector('input.new_name').onblur=updateButton; var sexes=ui.create.selectlist([ ['male','男'], ['female','女'], ['double','双性'], ['none','无'] ],null,ui.create.div('.indent','性别:',newCharacter)); var grouplist=lib.group.map((group,i)=>[lib.group[i],get.translation(lib.group[i])]); var groups=ui.create.selectlist(grouplist,null,ui.create.div('.indent','势力:',newCharacter)); var dieaudio=ui.create.div('.die_audio',newCharacter,{textAlign:'left'}); var dieaudiolabel=ui.create.node('label','阵亡配音:',dieaudio); var dieaudioUpload=dieaudio.appendChild(document.createElement('input')); dieaudioUpload.type='file'; dieaudioUpload.accept='audio/*'; dieaudioUpload.style.width='calc(100% - 100px)'; dieaudioUpload.onchange=function(){ var fileToLoad=dieaudioUpload.files[0]; if(fileToLoad){ console.log(fileToLoad); var fileReader=new FileReader(); fileReader.onload=function(fileLoadedEvent){ var data=fileLoadedEvent.target.result; var blob=new Blob([data]); dieaudio.file=fileToLoad; dieaudio.arrayBuffer=data; dieaudio.blob=blob; var new_name=newCharacter.querySelector('input.new_name'); dieaudioUpload.style.display='none'; dieaudiopreview.style.display= dieaudiocancel.style.display=''; dieaudiotag.src=window.URL.createObjectURL(blob); }; fileReader.readAsArrayBuffer(fileToLoad); } }; var dieaudiotag=ui.create.node('audio',dieaudio); var dieaudiopreview=ui.create.node('button',dieaudio,()=>{ if(dieaudiotag.error){ alert('您使用的客户端不支持预览此音频!') } else dieaudiotag.play(); }); dieaudiopreview.innerHTML='播放'; dieaudiopreview.style.display='none'; var dieaudiocancel=ui.create.node('button',dieaudio,()=>{ dieaudiopreview.style.display='none'; dieaudiocancel.style.display='none'; if(dieaudio.blob){ window.URL.revokeObjectURL(dieaudio.blob); dieaudiotag.src=null; delete dieaudio.file; delete dieaudio.arrayBuffer; delete dieaudio.blob; } dieaudioUpload.value=''; dieaudioUpload.style.display=''; }); dieaudiocancel.innerHTML='取消'; dieaudiocancel.style.display='none'; var options=ui.create.div('.add_skill.options','主公BOSS仅点将可用
        隐匿技
        ',newCharacter); var addSkill=ui.create.div('.add_skill','添加技能
        ',newCharacter); var list=[]; for(var i in lib.character){ if(lib.character[i][3].length){ list.push([i,lib.translate[i]]); } } list.sort(function(a,b){ a=a[0];b=b[0]; var aa=a,bb=b; if(aa.includes('_')){ aa=aa.slice(aa.indexOf('_')+1); } if(bb.includes('_')){ bb=bb.slice(bb.indexOf('_')+1); } if(aa!=bb){ return aa>bb?1:-1; } return a>b?1:-1; }); var list2=[]; var skills=lib.character[list[0][0]][3]; for(var i=0;i{ createButton(i,value,fullskin); loadImage(file,value); }); } } else{ page.content={ pack:{ card:{}, translate:{} }, image:{} }; toggle.classList.add('on'); newCard.style.display=''; } updatePile(); }; ui.create.div('.config.more.margin-bottom','
        返回',page,function(){ ui.create.templayer(); page.hide(); pageboard.show(); }); page.content={ pack:{ card:{}, translate:{}, list:[] }, image:{} }; var newCard; var toggle=ui.create.div('.config.more.on','创建卡牌
        >
        ',page,function(){ this.classList.toggle('on'); if(this.classList.contains('on')){ newCard.style.display=''; } else{ newCard.style.display='none'; } }); var resetEditor=function(){ currentButton=null; toggle.classList.remove('on'); newCard.style.display='none'; fakeme.classList.remove('inited'); fakeme.classList.add('fullskin'); delete fakeme.image; delete fakeme.image64; fakeme.style.backgroundImage=''; fakeme.imagenode.style.backgroundImage=''; var inputs=newCard.querySelectorAll('input'); for(var i=0;i',newCard).style.paddingTop='8px'; ui.create.div('.indent','描述:',newCard).style.paddingTop='6px'; newCard.querySelector('input.new_name').onblur=updateButton; var codeButton=document.createElement('button'); newCard.appendChild(codeButton); codeButton.innerHTML='编辑代码'; codeButton.style.left='123px'; codeButton.style.top='66px'; codeButton.style.position='absolute'; var citeButton=document.createElement('button'); newCard.appendChild(citeButton); citeButton.innerHTML='引用代码'; citeButton.style.left='123px'; citeButton.style.top='90px'; citeButton.style.position='absolute'; citeButton.onclick=function(){ codeButton.style.display='none'; citeButton.style.display='none'; selectname.style.display=''; confirmcontainer.style.display=''; } var list=[]; for(var i in lib.card){ if(lib.translate[i]){ list.push([i,lib.translate[i]]); } } list.sort(function(a,b){ a=a[0];b=b[0]; var aa=a,bb=b; if(aa.includes('_')){ aa=aa.slice(aa.indexOf('_')+1); } if(bb.includes('_')){ bb=bb.slice(bb.indexOf('_')+1); } if(aa!=bb){ return aa>bb?1:-1; } return a>b?1:-1; }); var selectname=ui.create.selectlist(list,list[0],newCard); selectname.style.left='123px'; selectname.style.top='66px'; selectname.style.position='absolute'; selectname.style.display='none'; var confirmcontainer=ui.create.div(newCard); confirmcontainer.style.left='123px'; confirmcontainer.style.top='90px'; confirmcontainer.style.position='absolute'; confirmcontainer.style.display='none'; var citeconfirm=document.createElement('button'); citeconfirm.innerHTML='引用'; confirmcontainer.appendChild(citeconfirm); citeconfirm.onclick=function(){ codeButton.style.display=''; citeButton.style.display=''; selectname.style.display='none'; confirmcontainer.style.display='none'; container.code='card='+get.stringify(lib.card[selectname.value]); codeButton.onclick.call(codeButton); if(lib.translate[selectname.value+'_info']){ newCard.querySelector('input.new_description').value=lib.translate[selectname.value+'_info']; } } var citecancel=document.createElement('button'); citecancel.innerHTML='取消'; citecancel.style.marginLeft='3px'; confirmcontainer.appendChild(citecancel); citecancel.onclick=function(){ codeButton.style.display=''; citeButton.style.display=''; selectname.style.display='none'; confirmcontainer.style.display='none'; } codeButton.onclick=function(){ var node=container; ui.window.classList.add('shortcutpaused'); ui.window.classList.add('systempaused'); window.saveNonameInput=saveInput; if(node.aced){ ui.window.appendChild(node); node.editor.setValue(node.code,1); } else if(lib.device=='ios'){ ui.window.appendChild(node); if(!node.textarea){ var textarea=document.createElement('textarea'); editor.appendChild(textarea); node.textarea=textarea; lib.setScroll(textarea); } node.textarea.value=node.code; } else{ if(!window.CodeMirror){ lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,editor)); lib.init.css(lib.assetURL+'layout/default','codemirror'); } else{ lib.codeMirrorReady(node,editor); } } } var container=ui.create.div('.popup-container.editor'); var saveInput=function(){ var code; if(container.editor){ code=container.editor.getValue(); } else if(container.textarea){ code=container.textarea.value; } try{ var card=null; eval(code); if(card==null||typeof card!='object'){ throw('err'); } } catch(e){ if(e=='err'){ alert('代码格式有错误,请对比示例代码仔细检查'); } else{ var tip=lib.getErrorTip(e)||''; alert('代码语法有错误,请仔细检查('+e+')'+tip); } window.focus(); if(container.editor){ container.editor.focus(); } else if(container.textarea){ container.textarea.focus(); } return; } dash2.link.classList.add('active'); ui.window.classList.remove('shortcutpaused'); ui.window.classList.remove('systempaused'); container.delete(); container.code=code; delete window.saveNonameInput; }; var editor=ui.create.editor(container,saveInput); container.code='card={\n \n}\n\n\/*\n示例:\ncard={\n type:"basic",\n enable:true,\n filterTarget:true,\n content:function(){\n target.draw()\n },\n ai:{\n order:1,\n result:{\n target:1\n }\n }\n}\n此例的效果为目标摸一张牌\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'; var editnode=ui.create.div('.menubutton.large.new_card.disabled','创建卡牌',newCard,function(){ var name=page.querySelector('input.new_name').value; if(!name){ alert('请填写卡牌名\n提示:卡牌名格式为id+|+中文名,其中id必须惟一'); return; } name=name.split('|'); var translate=name[1]||name[0]; var info=page.querySelector('input.new_description').value; name=name[0]; if(currentButton){ if(currentButton.link!=name){ if(lib.card[name]||page.content.pack.card[name]){ alert('卡牌名与现有卡牌重复,请更改\n提示:卡牌名格式为id+|+中文名,其中id必须惟一'); return; } var extname; if(currentButton.classList.contains('fullskin')){ extname='.png'; } else{ extname='.jpg'; } page.content.image[name+extname]=page.content.image[currentButton.link+extname]; delete page.content.image[currentButton.link+extname]; delete page.content.pack.card[currentButton.link]; delete page.content.pack.translate[currentButton.link]; delete page.content.pack.translate[currentButton.link+'_info']; currentButton.link=name; } } else{ if(lib.card[name]||page.content.pack.card[name]){ alert('卡牌名与现有卡牌重复,请更改\n提示:卡牌名格式为id+|+中文名,其中id必须惟一'); return; } } if(fakeme.image){ if(fakeme.classList.contains('fullskin')){ page.content.image[name+'.png']=fakeme.image; delete page.content.image[name+'.jpg']; } else{ page.content.image[name+'.jpg']=fakeme.image; delete page.content.image[name+'.png']; } } else if(!fakeme.classList.contains('inited')){ alert('请选择一个卡牌背景'); return; } page.content.pack.translate[name]=translate; page.content.pack.translate[name+'_info']=info; try{ var card=null; eval(container.code); if(card==null||typeof card!='object'){ throw('err'); } page.content.pack.card[name]=card; } catch(e){ page.content.pack.card[name]={}; } if(fakeme.classList.contains('inited')){ if(fakeme.classList.contains('fullskin')){ page.content.pack.card[name].fullskin=true; delete page.content.pack.card[name].fullimage; } else{ page.content.pack.card[name].fullimage=true; delete page.content.pack.card[name].fullskin; } } if(this.innerHTML=='创建卡牌'){ createButton(name,fakeme.image64,fakeme.classList.contains('fullskin')); } else if(currentButton){ if(fakeme.image64){ if(fakeme.classList.contains('fullskin')){ currentButton.style.color=''; currentButton.style.textShadow=''; currentButton.imagenode.style.backgroundImage='url('+fakeme.image64+')'; currentButton.style.backgroundImage=''; currentButton.style.backgroundSize=''; currentButton.classList.add('fullskin'); } else{ currentButton.style.color='white'; currentButton.style.textShadow='black 0 0 2px'; currentButton.imagenode.style.backgroundImage=''; currentButton.style.backgroundImage='url('+fakeme.image64+')'; currentButton.style.backgroundSize='cover'; currentButton.classList.remove('fullskin'); } } currentButton.nodename.innerHTML=get.verticalStr(translate); } resetEditor(); updatePile(); dash2.link.classList.add('active'); }); var delnode=ui.create.div('.menubutton.large.new_card_delete','取消',editnode.parentNode,function(){ if(this.innerHTML=='删除'){ this.button.remove(); var name=this.button.link; delete dash2.content.pack.card[name]; delete dash2.content.pack.translate[name]; delete dash2.content.pack.translate[name+'_info']; delete dash2.content.image[name]; updatePile(); dash2.link.classList.add('active'); } resetEditor(); }); var editPile; var toggle2=ui.create.div('.config.more','编辑牌堆
        >
        ',page,function(){ this.classList.toggle('on'); if(this.classList.contains('on')){ editPile.style.display=''; } else{ editPile.style.display='none'; } }); editPile=ui.create.div('.edit_pile',page); editPile.style.display='none'; var cardpileadd=ui.create.div('.config.toggle.cardpilecfg.cardpilecfgadd',editPile); var pile=ui.create.div(editPile); page.pile=pile; var cardpileaddname=document.createElement('select'); var updatePile=function(){ cardpileaddname.innerHTML=''; var list=[]; var list2=[]; for(var i in page.content.pack.card){ list.push([i,page.content.pack.translate[i]]); list2.push(i); } if(list.length){ toggle2.style.display=''; if(toggle2.classList.contains('on')){ editPile.style.display=''; } else{ editPile.style.display='none'; } for(var i=0;i
        返回',page,function(){ ui.create.templayer(); page.hide(); if(page.fromchar){ dash1.show(); delete page.fromchar; } else{ pageboard.show(); } }); var currentButton=null; var clickButton=function(){ if(currentButton==this){ resetEditor(); return; } resetEditor(); currentButton=this; toggle.classList.add('on'); newSkill.style.display=''; if(page.content.pack.translate[this.link]!=this.link){ newSkill.querySelector('.new_name').value=this.link+'|'+page.content.pack.translate[this.link]; } else{ newSkill.querySelector('.new_name').value=this.link; } newSkill.querySelector('.new_description').value=page.content.pack.translate[this.link+'_info']; var info=page.content.pack.skill[this.link]; container.code='skill='+get.stringify(info); toggle.innerHTML='编辑技能
        >
        '; editnode.innerHTML='编辑技能'; editnode.classList.remove('disabled'); delnode.button=this; delnode.innerHTML='删除'; } var createButton=function(name){ var button=ui.create.div('.menubutton'); button.link=name; button.innerHTML=page.content.pack.translate[name]; button.listen(clickButton); page.insertBefore(button,page.childNodes[1]); } var newSkill; var toggle=ui.create.div('.config.more.on','创建技能
        >
        ',page,function(){ this.classList.toggle('on'); if(this.classList.contains('on')){ newSkill.style.display=''; } else{ newSkill.style.display='none'; } }); page.toggle=toggle; var resetEditor=function(){ currentButton=null; toggle.classList.remove('on'); newSkill.style.display='none'; var inputs=newSkill.querySelectorAll('input'); for(var i=0;i',newSkill); var descnode=ui.create.div('.config','描述:',newSkill); namenode.querySelector('input.new_name').onblur=updateButton; var commandline=ui.create.div('.config',newSkill); var editbutton=document.createElement('button'); editbutton.innerHTML='编辑代码'; commandline.appendChild(editbutton); editbutton.onclick=function(){ var node=container; ui.window.classList.add('shortcutpaused'); ui.window.classList.add('systempaused'); window.saveNonameInput=saveInput; if(node.aced){ ui.window.appendChild(node); node.editor.setValue(node.code,1); } else if(lib.device=='ios'){ ui.window.appendChild(node); if(!node.textarea){ var textarea=document.createElement('textarea'); editor.appendChild(textarea); node.textarea=textarea; lib.setScroll(textarea); } node.textarea.value=node.code; } else{ if(!window.CodeMirror){ lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,editor)); lib.init.css(lib.assetURL+'layout/default','codemirror'); } else{ lib.codeMirrorReady(node,editor); } } } var container=ui.create.div('.popup-container.editor'); var saveInput=function(){ var code; if(container.editor){ code=container.editor.getValue(); } else if(container.textarea){ code=container.textarea.value; } try{ var skill=null; eval(code); if(skill==null||typeof skill!='object'){ throw('err'); } } catch(e){ if(e=='err'){ alert('代码格式有错误,请对比示例代码仔细检查'); } else{ var tip=lib.getErrorTip(e)||''; alert('代码语法有错误,请仔细检查('+e+')'+tip); } window.focus(); if(container.editor){ container.editor.focus(); } else if(container.textarea){ container.textarea.focus(); } return; } dash3.link.classList.add('active'); ui.window.classList.remove('shortcutpaused'); ui.window.classList.remove('systempaused'); container.delete(); container.code=code; delete window.saveNonameInput; }; var editor=ui.create.editor(container,saveInput); container.code='skill={\n \n}\n\n\/*\n示例:\nskill={\n trigger:{player:"phaseJieshuBegin"},\n frequent:true,\n content:function(){\n player.draw()\n }\n}\n此例为闭月代码\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'; var citebutton=document.createElement('button'); citebutton.innerHTML='引用代码'; commandline.appendChild(citebutton); citebutton.onclick=function(){ editbutton.style.display='none'; citebutton.style.display='none'; selectname.style.display=''; skillopt.style.display=''; addSkillButton.style.display=''; cancelSkillButton.style.display=''; } var list=[]; for(var i in lib.character){ if(lib.character[i][3].length){ list.push([i,lib.translate[i]]); } } list.sort(function(a,b){ a=a[0];b=b[0]; var aa=a,bb=b; if(aa.includes('_')){ aa=aa.slice(aa.indexOf('_')+1); } if(bb.includes('_')){ bb=bb.slice(bb.indexOf('_')+1); } if(aa!=bb){ return aa>bb?1:-1; } return a>b?1:-1; }); list.push(['others','其它']); var list2=[]; var skills=lib.character[list[0][0]][3]; for(var i=0;ib?1:-1; }); selectname.onchange=function(){ var skills; skillopt.innerHTML=''; if(this.value=='others'){ skills=list3; for(var i=0;i←返回',page,function(){ ui.create.templayer(); page.hide(); pageboard.show(); }); page.reset=function(name){ page.content={}; if(lib.extensionPack[name]){ for(var i in dashes){ dashes[i].node.code=''; } for(var i in lib.extensionPack[name].code){ switch(typeof lib.extensionPack[name].code[i]){ case 'function':page.content[i]=lib.extensionPack[name].code[i].toString();break; case 'object':page.content[i]=i+'='+get.stringify(lib.extensionPack[name].code[i]);break; } } for(var i in page.content){ dashes[i].node.code=page.content[i]||''; } } else{ dashes.content.node.code='function(config,pack){\n \n}\n\n\/*\n函数执行时机为游戏数据加载之后、界面加载之前\n参数1扩展选项(见选项代码);参数2为扩展定义的武将、卡牌和技能等(可在此函数中修改)\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'; dashes.precontent.node.code='function(){\n \n}\n\n\/*\n函数执行时机为游戏数据加载之前,且不受禁用扩展的限制\n除添加模式外请慎用\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'; dashes.config.node.code='config={\n \n}\n\n\/*\n示例:\nconfig={\n switcher_example:{\n name:"示例列表选项",\n init:"3",\n item:{"1":"一","2":"二","3":"三"}\n },\n toggle_example:{\n name:"示例开关选项",\n init:true\n }\n}\n此例中传入的主代码函数的默认参数为{switcher_example:"3",toggle_example:true}\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'; dashes.help.node.code='help={\n \n}\n\n\/*\n示例:\nhelp={\n "帮助条目":"
        • 列表1-条目1
        • 列表1-条目2
        1. 列表2-条目1
        2. 列表2-条目2
      "\n}\n帮助内容将显示在菜单-选项-帮助中\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'; } }; var dashes={}; var createCode=function(str1,str2,sub,func,link,str){ var dash=ui.create.div('.menubutton.large.dashboard'); dashes[link]=dash; sub.appendChild(dash); dash.listen(func); dash.link=link; ui.create.div('',str1,dash); ui.create.div('',str2,dash); var container=ui.create.div('.popup-container.editor'); var saveInput=function(){ var code; if(container.editor){ code=container.editor.getValue(); } else if(container.textarea){ code=container.textarea.value; } try{ if(link=='content'||link=='precontent'){ var func=null; eval('func='+code); if(typeof func!='function'){ throw('err'); } } else if(link=='config'){ var config=null; eval(code); if(config==null||typeof config!='object'){ throw('err'); } } else if(link=='help'){ var help=null; eval(code); if(help==null||typeof help!='object'){ throw('err'); } } } catch(e){ if(e=='err'){ alert('代码格式有错误,请对比示例代码仔细检查'); } else{ var tip=lib.getErrorTip(e)||''; alert('代码语法有错误,请仔细检查('+e+')'+tip); } window.focus(); if(container.editor){ container.editor.focus(); } else if(container.textarea){ container.textarea.focus(); } return; } dash4.link.classList.add('active'); ui.window.classList.remove('shortcutpaused'); ui.window.classList.remove('systempaused'); container.delete(); container.code=code; page.content[link]=code; delete window.saveNonameInput; }; var editor=ui.create.editor(container,saveInput); container.code=str; dash.editor=editor; dash.node=container; dash.saveInput=saveInput; page.content[link]=str; }; var clickCode=function(){ var node=this.node; ui.window.classList.add('shortcutpaused'); ui.window.classList.add('systempaused'); window.saveNonameInput=this.saveInput; if(node.aced){ ui.window.appendChild(node); node.editor.setValue(node.code,1); } else if(lib.device=='ios'){ ui.window.appendChild(node); if(!node.textarea){ var textarea=document.createElement('textarea'); this.editor.appendChild(textarea); node.textarea=textarea; lib.setScroll(textarea); } node.textarea.value=node.code; } else{ if(!window.CodeMirror){ lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,this.editor)); lib.init.css(lib.assetURL+'layout/default','codemirror'); } else{ lib.codeMirrorReady(node,this.editor); } } }; page.content={} createCode('主','主代码',page,clickCode,'content','function(config,pack){\n \n}\n\n\/*\n函数执行时机为游戏数据加载之后、界面加载之前\n参数1扩展选项(见选项代码);参数2为扩展定义的武将、卡牌和技能等(可在此函数中修改)\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'); createCode('启','启动代码',page,clickCode,'precontent','function(){\n \n}\n\n\/*\n函数执行时机为游戏数据加载之前,且不受禁用扩展的限制\n除添加模式外请慎用\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'); createCode('选','选项代码',page,clickCode,'config','config={\n \n}\n\n\/*\n示例:\nconfig={\n switcher_example:{\n name:"示例列表选项",\n init:"3",\n item:{"1":"一","2":"二","3":"三"}\n },\n toggle_example:{\n name:"示例开关选项",\n init:true\n }\n}\n此例中传入的主代码函数的默认参数为{switcher_example:"3",toggle_example:true}\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'); createCode('帮','帮助代码',page,clickCode,'help','help={\n \n}\n\n\/*\n示例:\nhelp={\n "帮助条目":"
      • 列表1-条目1
      • 列表1-条目2
      1. 列表2-条目1
      2. 列表2-条目2
    "\n}\n帮助内容将显示在菜单-选项-帮助中\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/'); return page; }()); createDash('将','编辑武将',dash1); createDash('卡','编辑卡牌',dash2); createDash('技','编辑技能',dash3); createDash('码','编辑代码',dash4); }; if(!get.config('menu_loadondemand')) node._initLink(); }()); (function(){ var page=ui.create.div(''); var node=ui.create.div('.menubutton.large','获取扩展',start.firstChild,clickMode); node.mode='get'; var _thisUpdate=false; node.update=function(){ _thisUpdate=true; }; node._initLink=function(){ node.link=page; page.listen(function(){ if(!page.currenttimeout){ var active=page.querySelector('.videonode.current'); if(active){ active.classList.remove('current'); } } }); var importextensionexpanded=false; page.style.paddingBottom='10px'; var importExtension; var extensionNode=ui.create.div('.config.more','导入扩展
    >
    ',page,function(){ if(importextensionexpanded){ this.classList.remove('on'); importExtension.style.display='none'; } else{ this.classList.add('on'); importExtension.style.display=''; } importextensionexpanded=!importextensionexpanded; }); importExtension=ui.create.div('.new_character.export.import',page); importExtension.style.marginLeft='5px'; importExtension.style.marginTop='5px'; importExtension.style.marginBottom='5px'; importExtension.style.display='none'; importExtension.style.width='100%'; importExtension.style.textAlign='left'; ui.create.div('','',importExtension); ui.create.div('.config','修改下载地址',page,function(){ alert('您可以在“设置→通用→获取扩展地址”中,修改下载扩展时所采用的地址。') }) var extensionURL; var source=lib.config.extension_sources,index=lib.config.extension_source; if(source&&source[index]) extensionURL=source[index]; else extensionURL=lib.updateURL.replace(/noname/g,'noname-extension')+'/master/'; var reloadnode=ui.create.div('.config.toggle.pointerdiv','重新启动',page,game.reload); reloadnode.style.display='none'; var placeholder=ui.create.div('.config.toggle',page); placeholder.style.height=0; placeholder.style.marginTop='5px'; importExtension.firstChild.lastChild.onclick=function(){ const fileToLoad=this.previousSibling.files[0]; if(!fileToLoad) return; new Promise((resolve,reject)=>{ const fileReader=new FileReader(); fileReader.onerror=reject; fileReader.onload=resolve; fileReader.readAsArrayBuffer(fileToLoad,"UTF-8"); }).then(progressEvent=>{ if(game.importExtension(progressEvent.target.result,()=>{ extensionNode.innerHTML='导入成功,3秒后将重启'; new Promise(resolve=>setTimeout(resolve,1000)).then(()=>{ extensionNode.innerHTML='导入成功,2秒后将重启'; return new Promise(resolve=>setTimeout(resolve,1000)); }).then(()=>{ extensionNode.innerHTML='导入成功,1秒后将重启'; return new Promise(resolve=>setTimeout(resolve,1000)); }).then(game.reload); })!==false) importExtension.style.display='none'; }); } var clickExtension=function(){ var active=this.parentNode.querySelector('.videonode.current'); if(active&&active!=this){ active.classList.remove('current'); } this.classList.add('current'); clearTimeout(page.currenttimeout); page.currenttimeout=setTimeout(function(){ delete page.currenttimeout; },200); }; var downloadExtension=function(e){ if((this.innerHTML!='下载扩展'&&this.innerHTML!='更新扩展')||!window.JSZip) return; this.classList.remove('update'); if(e){ e.stopPropagation(); } node.updated=true; var that=this; var list=[]; var size=parseFloat(this.info.size)||0; if(size){ if(this.info.size.includes('MB')){ size*=1024*1024; } else if(this.info.size.includes('KB')){ size*=1024; } } this.innerHTML='正在下载
    正在下载
    '; this.classList.add('nopointer'); this.classList.add('button-downloading'); var progress=ui.create.div('.button-progress',this); ui.create.div(progress); var url=extensionURL+this.info.name+'.zip'; var onprogress=function(byte,total){ if(total){ size=total; } if(byte==-1){ byte=size; } progress.firstChild.style.width=Math.round(100*byte/size)+'%'; }; var files=this.info.files||[]; for(var i=0;i('+list[i].size+')',node); ui.create.div('.text','更新日期:'+list[i].date,node); ui.create.div('.text',list[i].intro,node); var download=ui.create.div('.menubutton.text.active','下载扩展',node.firstChild,{'zIndex':'5'}); if(game.download){ if(list[i].netdisk){ var linknode=ui.create.div('.text',node); ui.create.node('span.hrefnode','网盘链接',function(){ game.open(this.link); },linknode).link=list[i].netdisk; if(list[i].forum){ ui.create.node('span',linknode).style.marginRight='10px'; ui.create.node('span.hrefnode','参与讨论',function(){ game.open(this.link); },linknode).link=list[i].forum; } } else if(list[i].forum){ var linknode=ui.create.div('.text',node); ui.create.node('span.hrefnode','参与讨论',function(){ game.open(this.link); },linknode).link=list[i].forum; } download.listen(downloadExtension); if(lib.config.extensions.includes(list[i].name)){ download.classList.remove('active'); if(lib.extensionPack[list[i].name]&&lib.extensionPack[list[i].name].version==list[i].version){ download.classList.add('transparent2'); download.classList.remove('active'); download.innerHTML='已安装'; } else if(lib.config['extension_'+list[i].name+'_version']!=list[i].version){ download.innerHTML='更新扩展'; download.classList.add('highlight'); download.classList.add('update'); } else{ download.classList.add('transparent2'); download.classList.remove('active'); download.innerHTML='已安装'; } } download.info=list[i]; } else{ if(list[i].forum){ var linknode=ui.create.div('.text',node); ui.create.node('span',linknode); ui.create.node('span.hrefnode','参与讨论',function(){ game.open(this.link); },linknode).link=list[i].forum; } download.listen(function(){ game.open(this.link); }); download.link=list[i].netdisk; } } }; window.extension={}; fetch(`${extensionURL}catalog.js`,{ referrerPolicy:'no-referrer' }).then(response=>response.text()).then(eval).then(loaded).catch(reason=>{ console.log(reason); delete window.extension; loading.innerHTML='连接失败:'+(reason instanceof Error?reason.message:String(reason)); }); }; if(_thisUpdate) node.update(); }; if(!get.config('menu_loadondemand')) node._initLink(); }()); var active=start.firstChild.querySelector('.active'); if(!active){ active=start.firstChild.firstChild; active.classList.add('active'); } if(!active.link) active._initLink(); rightPane.appendChild(active.link); updateNodes(); }()); (function(){ if(connectMenu) return; var start=menuxpages.shift(); var rightPane=start.lastChild; var cheatButton=ui.create.div('.menubutton.round.highlight','作',start); cheatButton.style.display='none'; var runButton=ui.create.div('.menubutton.round.highlight','执',start); runButton.style.display='none'; var clearButton=ui.create.div('.menubutton.round.highlight','清',start); clearButton.style.display='none'; clearButton.style.left='275px'; var playButton=ui.create.div('.menubutton.round.highlight.hidden','播',start); playButton.style.display='none'; playButton.style.left='215px'; playButton.style.transition='opacity 0.3s'; var deleteButton=ui.create.div('.menubutton.round.highlight.hidden','删',start); deleteButton.style.display='none'; deleteButton.style.left='275px'; deleteButton.style.transition='opacity 0.3s'; var saveButton=ui.create.div('.menubutton.round.highlight.hidden','存',start); saveButton.style.display='none'; saveButton.style.transition='opacity 0.3s'; var clickMode=function(){ if(this.classList.contains('off')) return; var active=this.parentNode.querySelector('.active'); if(active===this){ return; } if(active){ active.classList.remove('active'); active.link.remove(); } active=this; this.classList.add('active'); if(this.link) rightPane.appendChild(this.link); else{ this._initLink(); rightPane.appendChild(this.link); } if(this.type=='cheat'){ cheatButton.style.display=''; } else{ cheatButton.style.display='none'; } if(this.type=='cmd'){ runButton.style.display=''; clearButton.style.display=''; } else{ runButton.style.display='none'; clearButton.style.display='none'; } if(this.type=='video'){ playButton.style.display=''; saveButton.style.display=''; deleteButton.style.display=''; } else{ playButton.style.display='none'; saveButton.style.display='none'; deleteButton.style.display='none'; } }; ui.click.consoleMenu=function(){ ui.click.menuTab('其它'); clickMode.call(ui.commandnode); }; //更新菜单有本体函数赋值,就不要懒加载了 (function(){ var page=ui.create.div(''); var node=ui.create.div('.menubutton.large','更新',start.firstChild,clickMode); node.link=page; page.classList.add('menu-help'); var ul=document.createElement('ul'); var li1=document.createElement('li'); var li2=document.createElement('li'); var li3=document.createElement('li'); const trimURL=url=>{ const updateURLS=lib.updateURLS; for(const key in updateURLS){ const updateURL=updateURLS[key]; if(url==updateURL) return lib.configMenu.general.config.update_link.item[key]; } let index=url.indexOf('://'); if(index!=-1) url=url.slice(index+3); index=url.indexOf('/'); if(index!=-1) url=url.slice(0,index); if(url.length>15){ const list=url.split('.'); if(list.length>1) list.shift(); url=list.join('.'); } if(url.length>15){ const list=url.split('.'); if(list.length>1) list.pop(); url=list.join('.'); } return url; } li1.innerHTML='游戏版本:'+lib.version+'

    '; li2.innerHTML='素材版本:'+(lib.config.asset_version||'无')+'

    '; li3.innerHTML='更新地址:'+trimURL(lib.config.updateURL||lib.updateURL)+'

    '; li3.style.whiteSpace='nowrap'; li3.style.display='none';// coding var button1,button2,button3,button4,button5; game.checkForUpdate=function(forcecheck,dev){ if(!dev&&button1.disabled){ return; } else if(dev&&button3.disabled){ return; } else if(!game.download){ alert('此版本不支持游戏内更新,请手动更新'); return; } else{ if(dev){ button3.innerHTML='正在检查更新'; } else{ button1.innerHTML='正在检查更新'; } button3.disabled=true; button1.disabled=true; var goupdate=function(files,update){ lib.version=update.version; if(update.dev&&!lib.config.debug){ dev='nodev'; } lib.init.req('game/source.js',function(){ try{ eval(this.responseText); if(!window.noname_source_list){ throw('err'); } } catch(e){ alert('更新地址有误'); console.log(e); return; } var updates=window.noname_source_list; delete window.noname_source_list; if(Array.isArray(files)){ files.add('game/update.js'); var files2=[]; for(var i=0;iversion1[i]){ files=false;break; } else if(version1[i]>version2[i]){ files=update.files.slice(0);break; } } if(files===null){ if(version1.length>=version2.length){ files=update.files.slice(0); } } } var str; if(dev){ str='开发版仅供测试使用,可能存在风险,是否确定更新?' } else{ str='有新版本'+update.version+'可用,是否下载?'; } if(navigator.notification&&navigator.notification.confirm){ var str2; if(dev){ str2=str; str='更新到开发版'; } else{ str2=update.changeLog[0]; for(var i=1;i>'); span1.style.fontSize='small'; span1.style.display='inline'; span1.toggle=function(){ if(!this.classList.toggle('on')){ game.saveConfig('asset_toggle_off',true); span2.style.display='none'; span2_br.style.display='none'; span2_check.style.display='none'; span3.style.display='none'; span3_br.style.display='none'; span3_check.style.display='none'; span4.style.display='none'; span4_br.style.display='none'; span4_check.style.display='none'; span5.style.display='none'; span5_br.style.display='none'; span5_check.style.display='none'; span6.style.display='none'; span6_br.style.display='none'; span6_check.style.display='none'; } else{ game.saveConfig('asset_toggle_off'); span2.style.display=''; span2_br.style.display=''; span2_check.style.display=''; span3.style.display=''; span3_br.style.display=''; span3_check.style.display=''; span4.style.display=''; span4_br.style.display=''; span4_check.style.display=''; span5.style.display=''; span5_br.style.display=''; span5_check.style.display=''; span6.style.display=''; span6_br.style.display=''; span6_check.style.display=''; } }; span1.listen(span1.toggle); li2.lastChild.appendChild(span1); var span6_br=ui.create.node('br'); li2.lastChild.appendChild(span6_br); var span5=ui.create.div('','图片素材(精简,126MB)'); span5.style.fontSize='small'; span5.style.lineHeight='16px'; var span5_check=document.createElement('input'); span5_check.type='checkbox'; span5_check.style.marginLeft='5px'; if(lib.config.asset_image){ span5_check.checked=true; } span5_check.onchange=function(){ game.saveConfig('asset_image',this.checked); } var span2_br=ui.create.node('br'); var span4=ui.create.div('','字体素材(48MB)'); span4.style.fontSize='small'; span4.style.lineHeight='16px'; li2.lastChild.appendChild(span4); var span4_check=document.createElement('input'); span4_check.type='checkbox'; span4_check.style.marginLeft='5px'; if(lib.config.asset_font){ span4_check.checked=true; } span4_check.onchange=function(){ game.saveConfig('asset_font',this.checked); } li2.lastChild.appendChild(span4_check); var span3_br=ui.create.node('br'); li2.lastChild.appendChild(span3_br); var span3=ui.create.div('','音效素材(125MB)'); span3.style.fontSize='small'; span3.style.lineHeight='16px'; li2.lastChild.appendChild(span3); var span3_check=document.createElement('input'); span3_check.type='checkbox'; span3_check.style.marginLeft='5px'; if(lib.config.asset_audio){ span3_check.checked=true; } span3_check.onchange=function(){ game.saveConfig('asset_audio',this.checked); } li2.lastChild.appendChild(span3_check); var span4_br=ui.create.node('br'); li2.lastChild.appendChild(span4_br); var span2=ui.create.div('','皮肤素材(351MB)'); span2.style.fontSize='small'; span2.style.lineHeight='16px'; li2.lastChild.appendChild(span2); var span2_check=document.createElement('input'); span2_check.type='checkbox'; span2_check.style.marginLeft='5px'; if(lib.config.asset_skin){ span2_check.checked=true; } span2_check.onchange=function(){ game.saveConfig('asset_skin',this.checked); } li2.lastChild.appendChild(span2_check); var span5_br=ui.create.node('br'); li2.lastChild.appendChild(span5_br); li2.lastChild.appendChild(span5); li2.lastChild.appendChild(span5_check); li2.lastChild.appendChild(span2_br); var span6=ui.create.div('','图片素材(完整,203MB)'); span6.style.fontSize='small'; span6.style.lineHeight='16px'; li2.lastChild.appendChild(span6); var span6_check=document.createElement('input'); span6_check.type='checkbox'; span6_check.style.marginLeft='5px'; if(lib.config.asset_full){ span6_check.checked=true; } span6_check.onchange=function(){ game.saveConfig('asset_full',this.checked); } li2.lastChild.appendChild(span6_check); span2.style.display='none'; span2_br.style.display='none'; span2_check.style.display='none'; span3.style.display='none'; span3_br.style.display='none'; span3_check.style.display='none'; span4.style.display='none'; span4_br.style.display='none'; span4_check.style.display='none'; span5.style.display='none'; span5_br.style.display='none'; span5_check.style.display='none'; span6.style.display='none'; span6_br.style.display='none'; span6_check.style.display='none'; ul.appendChild(li1); ul.appendChild(li2); ul.appendChild(li3); page.appendChild(ul); if(!lib.config.asset_toggle_off){ span1.toggle(); } }()); (function(){ var norow2=function(){ var node=currentrow1; if(!node) return false; return node.innerHTML=='横置'||node.innerHTML=='翻面'||node.innerHTML=='换人'||node.innerHTML=='复活'; }; var checkCheat=function(){ if(norow2()){ for(var i=0;i=0){ logindex--; if(logindex<0){ text2.value=''; } else{ text2.value=logs[logindex]; } } else{ text2.value=''; } } else if(text2.value.includes('无天使')&&(text2.value.includes('无神佛')||text2.value.includes('无神')&&text2.value.includes('无佛'))){ game.print('密码正确!欢迎来到死后世界战线!'); _status.keyVerified=true; text2.value=''; } else{ if(!game.observe&&!game.online){ try{ var value=text2.value.trim(); if(value.endsWith(";")) value=value.slice(0,-1).trim(); var result=fun(reg,value,_status,lib,game,ui,get,ai); game.print(result); } catch(e){ game.print(e); } } text2.value=''; } } text2.addEventListener('keydown',function(e){ if(e.keyCode==13){ runCommand(); } else if(e.keyCode==38){ if(logindex+1=0){ logindex--; if(logindex<0){ text2.value=''; } else{ text2.value=logs[logindex]; } } } }); page.appendChild(text2); game.print=function(){ var args=[].slice.call(arguments); var printResult=args.map(arg=>{ if(get.is.object(arg)||typeof arg=='function'){ var argi=get.stringify(arg); if(argi/*&&argi.length<5000*/){ return argi.replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } else return arg.toString(); }else{ var str=String(arg); if (!/<[a-zA-Z]+[^>]*?\/?>.*?(?=<\/[a-zA-Z]+[^>]*?>|$)/.exec(str)) return String(arg) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); else return str; } }).join(' '); pre.innerHTML+=printResult+'
    '; text.scrollTop=text.scrollHeight; } if(_status.toprint){ for(var i=0;i<_status.toprint.length;i++){ game.print.apply(this,_status.toprint[i]); } delete _status.toprint; } runButton.listen(runCommand); clearButton.listen(function(){ pre.innerHTML=''; }); }; if(!get.config('menu_loadondemand')) node._initLink(); }()); (function(){ var page=ui.create.div(''); var node=ui.create.div('.menubutton.large','战绩',start.firstChild,clickMode); node.type='rec'; node._initLink=function(){ node.link=page; page.style.paddingBottom='10px'; var reset=function(){ if(this.innerHTML=='重置'){ this.innerHTML='确定'; var that=this; setTimeout(function(){ that.innerHTML='重置'; },1000); } else{ this.parentNode.previousSibling.remove(); this.parentNode.remove(); lib.config.gameRecord[this.parentNode.link]={data:{}}; game.saveConfig('gameRecord',lib.config.gameRecord); } } for(var i=0;i重置',page); item.style.height='auto'; item.lastChild.addEventListener('click',reset); item.lastChild.classList.add('pointerdiv'); item.link=lib.config.all.mode[i]; } } }; if(!get.config('menu_loadondemand')) node._initLink(); }()); (function(){ if(!window.indexedDB||window.nodb) return; var page=ui.create.div(''); var node=ui.create.div('.menubutton.large','录像',start.firstChild,clickMode); node.type='video'; lib.videos=[]; ui.create.videoNode=(video,before)=>lib.videos[before===true?'unshift':'push'](video); node._initLink=function(){ node.link=page; var store=lib.db.transaction(['video'],'readwrite').objectStore('video'); store.openCursor().onsuccess=function(e){ var cursor=e.target.result; if(cursor){ lib.videos.push(cursor.value); cursor.continue(); } else{ lib.videos.sort(function(a,b){ return parseInt(b.time)-parseInt(a.time); }); var clickcapt=function(){ var current=this.parentNode.querySelector('.videonode.active'); if(current&¤t!=this){ current.classList.remove('active'); } if(this.classList.toggle('active')){ playButton.show(); deleteButton.show(); saveButton.show(); } else{ playButton.hide(); deleteButton.hide(); saveButton.hide(); } }; var staritem=function(){ this.parentNode.classList.toggle('starred'); var store=lib.db.transaction(['video'],'readwrite').objectStore('video'); if(this.parentNode.classList.contains('starred')){ this.parentNode.link.starred=true; } else{ this.parentNode.link.starred=false; } store.put(this.parentNode.link); } var createNode=function(video,before){ var node=ui.create.div('.videonode.menubutton.large',clickcapt); node.link=video; var nodename1=ui.create.div('.menubutton.videoavatar',node); nodename1.setBackground(video.name1,'character'); if(video.name2){ var nodename2=ui.create.div('.menubutton.videoavatar2',node); nodename2.setBackground(video.name2,'character'); } var date=new Date(video.time); var str=date.getFullYear()+'.'+(date.getMonth()+1)+'.'+(date.getDate())+' '+ date.getHours()+':'; var minutes=date.getMinutes(); if(minutes<10){ str+='0'; } str+=minutes; ui.create.div('.caption',video.name[0],node); ui.create.div('.text',str+'
    '+video.name[1],node); if(video.win){ ui.create.div('.victory','胜',node); } if(before){ page.insertBefore(node,page.firstChild); } else{ page.appendChild(node); } ui.create.div('.video_star','★',node,staritem); if(video.starred){ node.classList.add('starred'); } } for(var i=0;i导入录像...',function(){ this.nextSibling.classList.toggle('hidden'); },page); importVideoNode.style.marginLeft='12px'; importVideoNode.style.marginTop='3px'; var importVideo=ui.create.div('.config.hidden',page); importVideo.style.whiteSpace='nowrap'; importVideo.style.marginBottom='80px'; importVideo.style.marginLeft='13px'; importVideo.style.width='calc(100% - 30px)'; importVideo.innerHTML=''+ ''; importVideo.lastChild.onclick=function(){ var fileToLoad = importVideo.firstChild.files[0]; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent) { var data = fileLoadedEvent.target.result; if(!data) return; try{ data=JSON.parse(lib.init.decode(data)); } catch(e){ console.log(e); alert('导入失败'); return; } var store=lib.db.transaction(['video'],'readwrite').objectStore('video'); var videos=lib.videos.slice(0); for(var i=0;i=parseInt(lib.config.video)&&videos.length){ var toremove=videos.pop(); lib.videos.remove(toremove); store.delete(toremove.time); for(var i=0;iposition2){ position.insertBefore(node,position.childNodes[position2]); } else{ position.appendChild(node); } } return node; }, giveup:function(){ if(ui.giveup) return; if(!lib.config.show_giveup) return; ui.giveup=ui.create.system('投降',function(){ var player=game.me; this.remove(); if(game.online){ game.send('giveup',player); } else{ _status.event.next.length=0; game.createEvent('giveup',false).set('includeOut',true).setContent(function(){ game.log(player,'投降'); player.popup('投降'); player.die('nosource').includeOut=true; }).player=player; } if(_status.paused&&_status.imchoosing&&!_status.auto){ ui.click.auto(); } },true,true); }, groupControl:function(dialog){ return ui.create.control('wei','shu','wu','qun','jin','western','key',function(link,node){ if(link=='全部'){ dialog.currentcapt=''; dialog.currentgroup=''; for(var i=0;ib?1:-1; }); groups.sort(lib.sort.group); if(!thisiscard){ namecapt.remove('自定义'); namecapt.push('newline'); for(var i in lib.characterDialogGroup){ namecapt.push(i); } } var newlined=false; var newlined2; var packsource; var clickCapt=function(e){ if(_status.dragged) return; if(dialog.currentcapt2=='最近'&&dialog.currentcaptnode2!=this&&!dialog.currentcaptnode2.inited){ dialog.currentcapt2=null; dialog.currentcaptnode2.classList.remove('thundertext'); dialog.currentcaptnode2.inited=true; dialog.currentcaptnode2=null; } if(this.alphabet){ if(this.classList.contains('thundertext')){ dialog.currentcapt=null; dialog.currentcaptnode=null; this.classList.remove('thundertext'); if(this.touchlink){ this.touchlink.classList.remove('active'); } for(var i=0;i0){ filternode.firstChild.style.top=(dh/2)+'px'; } else{ filternode.firstChild.style.top=''; } } else{ if(newlined2.style.display=='none'){ newlined2.style.display='block'; } else{ newlined2.style.display='none'; } } }); var packlist=[]; for(var i=0;ib?1:-1; } return aa>bb?1:-1; }); } else{ list.sort(lib.sort.character); } dialog=ui.create.dialog('hidden'); dialog.classList.add('noupdate'); dialog.classList.add('scroll1'); dialog.classList.add('scroll2'); dialog.classList.add('scroll3'); dialog.addEventListener(lib.config.touchscreen?'touchend':'mouseup',function(){ _status.clicked2=true; }); if(heightset){ dialog.style.height=((game.layout=='long2'||game.layout=='nova')?380:350)+'px'; dialog._scrollset=true; } dialog.getCurrentCapt=function(link,capt,noalph){ var currentcapt=noalph?this.currentcapt2:this.currentcapt; if(this.seperatelist&&noalph){ if(this.seperatelist[currentcapt].contains(link)) return capt; return null; } if(lib.characterDialogGroup[currentcapt]){ return lib.characterDialogGroup[currentcapt](link,capt); } if(lib.characterPack[currentcapt]){ if(lib.characterPack[currentcapt][link]){ return capt; } return null; } return this.currentcapt; } if(str){ dialog.add(str); } dialog.add(node); if(thisiscard){ if(seperate){ seperate=seperate(list); dialog.seperate=[]; dialog.seperatelist=seperate.list; if(dialog.seperatelist){ newlined=document.createElement('div'); newlined.style.marginTop='5px'; newlined.style.display='block'; newlined.style.fontFamily='xinwei'; if(get.is.phoneLayout()){ newlined.style.fontSize='32px'; } else{ newlined.style.fontSize='22px'; } newlined.style.textAlign='center'; node.appendChild(newlined); for(var i in dialog.seperatelist){ var span=document.createElement('span'); span.style.margin='3px'; span.innerHTML=i; span.link=i; span.seperate=true; span.addEventListener(lib.config.touchscreen?'touchend':'click',clickCapt); newlined.appendChild(span); } } for(var i in seperate){ if(i=='list') continue; var link=''; var linkcontent=seperate[i]; if(i.includes('_link:')){ link=i.slice(i.indexOf('_link:')+6); i=i.slice(0,i.indexOf('_link:')); } var nodesep=dialog.add(i); nodesep.link=link; dialog.seperate.push(nodesep); dialog.add([linkcontent,'vcard'],noclick); } } else{ dialog.add([list,'vcard'],noclick); } } else{ if(precharacter){ dialog.add([list,'precharacter'],noclick); } else if(characterx){ dialog.add([list,'characterx'],noclick); } else{ dialog.add([list,'character'],noclick); } } dialog.add(ui.create.div('.placeholder')); for(i=0;i=3600){ var num1=Math.floor(num/3600); var num2=Math.floor((num-num1*3600)/60); if(num2<10){ num2='0'+num2.toString(); } var num3=num-num1*3600-parseInt(num2)*60; if(num3<10){ num3='0'+num3.toString(); } ui.time3.innerHTML=num1+':'+num2+':'+num3; } else{ var num1=Math.floor(num/60); var num2=num-num1*60; if(num2<10){ num2='0'+num2.toString(); } ui.time3.innerHTML=num1+':'+num2; } },1000); } if(get.is.nomenu()){ if(!['menu','system'].contains(lib.config.round_menu_func)){ lib.config.round_menu_func='system'; } } else if(!lib.config.show_round_menu){ ui.roundmenu.style.display='none'; } var resetround=function(e){ _status.draggingroundmenu=false; ui.roundmenu.style.transform=''; ui.roundmenu._dragtransform=[0,0]; ui.roundmenu.style.transition='all 0.3s'; delete ui.roundmenu._dragtouches; delete ui.roundmenu._dragorigin; delete ui.roundmenu._dragorigintransform; setTimeout(function(){ ui.roundmenu.style.transition=''; },500); game.saveConfig('roundmenu_transform',[0,0]); if(e) e.stopPropagation(); return false; }; ui.click.resetround=resetround; if(lib.config.touchscreen){ ui.roundmenu.addEventListener('touchstart',function(e){ _status.draggingroundmenu=true; ui.roundmenu._dragorigin={ clientX:e.touches[0].clientX, clientY:e.touches[0].clientY, }; if(!ui.roundmenu._dragtransform){ ui.roundmenu._dragtransform=[0,0]; } ui.roundmenu._dragorigintransform=ui.roundmenu._dragtransform.slice(0); ui.roundmenu._resetTimeout=setTimeout(function(){ resetround(); delete ui.roundmenu._resetTimeout; },1000); }); } else{ ui.roundmenu.oncontextmenu=resetround; } if(!lib.config.remember_round_button){ game.saveConfig('roundmenu_transform'); } if(lib.config.roundmenu_transform){ var translate=lib.config.roundmenu_transform; ui.roundmenu._dragtransform=translate; ui.roundmenu.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)'; ui.click.checkroundtranslate(); } if(get.is.phoneLayout()){ ui.arena.classList.add('phone'); } ui.sidebar=ui.create.div('#sidebar'); ui.sidebar3=ui.create.div('#sidebar3'); ui.canvas=document.createElement('canvas'); ui.arena.appendChild(ui.canvas); ui.canvas.id='canvas'; ui.ctx=ui.canvas.getContext('2d'); ui.sidebar.ontouchstart=ui.click.touchStart; ui.sidebar.ontouchmove = ui.click.touchScroll; ui.sidebar.style.webkitOverflowScrolling='touch'; var zoom; switch(lib.config.ui_zoom){ case 'esmall':zoom=0.8;break; case 'vsmall':zoom=0.9;break; case 'small':zoom=0.93;break; case 'big':zoom=1.05;break; case 'vbig':zoom=1.1;break; case 'ebig':zoom=1.2;break; case 'eebig':zoom=1.5;break; case 'eeebig':zoom=1.8;break; case 'eeeebig':zoom=2;break; default:zoom=1; } game.documentZoom=game.deviceZoom*zoom; if(zoom!=1){ ui.updatez(); } ui.system1=ui.create.div('#system1',ui.system); ui.system2=ui.create.div('#system2',ui.system); ui.replay=ui.create.system('重来',game.reload,true); ui.replay.id='restartbutton'; ui.config2=ui.create.system('选项',ui.click.config); ui.pause=ui.create.system('暂停',ui.click.pause); ui.pause.id='pausebutton'; if(!_status.video){ ui.pause.hide(); } if(!lib.config.touchscreen){ lib.setPopped(ui.pause,ui.click.pausehistory,220,400,null,true); } if(!lib.config.show_pause){ ui.pause.style.display='none'; } ui.cardPileButton=ui.create.system('牌堆',null,true); ui.cardPileButton.style.display='none'; lib.setPopped(ui.cardPileButton,ui.click.cardPileButton,220); ui.wuxie=ui.create.system('不询问无懈',ui.click.wuxie,true); if(!lib.config.touchscreen){ lib.setPopped(ui.config2,ui.click.pauseconfig,170); } ui.auto=ui.create.system('托管',ui.click.auto); if(!game.syncMenu){ ui.config2.classList.add('hidden'); ui.config2.style.transition='all 0.5s'; ui.roundmenu.classList.add('transparent2'); ui.auto.style.opacity=0.5; ui.auto.style.transition='all 0.5s'; lib.onfree.push(function(){ ui.auto.style.opacity=''; setTimeout(function(){ ui.auto.style.transition=''; },500); }); } ui.auto.id='autobutton'; ui.autonode=ui.create.div('#autonode','
    托管中...
    ',ui.arena); ui.autonode.listen(ui.click.auto); if(lib.config.mode=='connect'){ ui.auto.hide(); ui.pause.hide(); } if(lib.forcehide){ if(lib.forcehide.contains('replay')) ui.replay.classList.add('forcehide'); if(lib.forcehide.contains('auto')) ui.auto.classList.add('forcehide'); if(lib.forcehide.contains('pause')) ui.pause.classList.add('forcehide'); if(lib.forcehide.contains('wuxie')) ui.wuxie.classList.add('forcehide'); if(lib.forcehide.contains('cardPileButton')) ui.cardPileButton.classList.add('forcehide'); } ui.volumn=ui.create.system('♫'); lib.setPopped(ui.volumn,ui.click.volumn,200); // if(lib.config.show_pause) ui.auto.style.marginLeft='10px'; if(!lib.config.show_volumn){ ui.volumn.style.display='none'; } if(!lib.config.show_auto){ ui.auto.style.display='none'; } if(!lib.config.show_wuxie){ ui.wuxie.style.display='none'; } // if(!lib.config.show_cardpile||_status.connectMode){ // ui.cardPileButton.style.display='none'; // } ui.sortCard=ui.create.system('整理手牌',function(){ if(!game.me) return; var hs=game.me.getCards('h'); if(!hs.length) return; game.addVideo('lose',game.me,[get.cardsInfo(hs),[],[],[]]); for(var i=0;i(getn(b)-getn(a))); } else hs.sort(function(b,a){ if(a.name!=b.name) return lib.sort.card(a.name,b.name); else if(a.suit!=b.suit) return lib.suit.indexOf(a)-lib.suit.indexOf(b); else return a.number-b.number; }); game.me.directgain(hs,false); }); if(!lib.config.show_sortcard){ ui.sortCard.style.display='none'; } ui.playerids=ui.create.system('显示身份',function(){ if(game.showIdentity){ game.showIdentity(); _status.identityShown=true; } },true); if(!lib.config.show_playerids||!game.showIdentity){ ui.playerids.style.display='none'; } if(!lib.config.show_replay){ ui.replay.style.display='none'; } ui.control=ui.create.div('#control',ui.arena).animate('nozoom'); ui.cardPile=ui.create.div('#cardPile'); ui.discardPile=ui.create.div('#discardPile'); ui.special=ui.create.div('#special'); ui.ordering=ui.create.div('#ordering'); ui.dialogs=[]; ui.controls=[]; ui.style={}; ui.time=ui.create.div(ui.gameinfo); var timeInterval=function(){ var date=new Date(); var hours=date.getHours(); var minutes=date.getMinutes(); if(lib.config.watchface=='simple'){ ui.roundmenu.childNodes[13].style.transform='rotate('+get.round((hours+9)*30,2)+'deg)'; } else{ ui.roundmenu.childNodes[13].style.transform='rotate('+get.round((hours+minutes/60+9)*30,2)+'deg)'; } ui.roundmenu.childNodes[12].style.transform='rotate('+(minutes+45)*6+'deg)'; if(minutes<10){ minutes='0'+minutes.toString(); } ui.time.innerHTML=hours+':'+minutes; }; _status.timeInterval=setInterval(timeInterval,30000); timeInterval(); if(!lib.config.show_time){ ui.time.style.display='none'; } ui.timer=ui.create.div('.skillbar.shadowed.playerbg.hidden'); ui.timer.id='timer'; ui.create.div('.skillbarshadow',ui.timer); ui.create.div('.skillbarfill',ui.timer); ui.timer.fillnode=ui.create.div(ui.timer.lastChild); ui.timer.popnode=ui.create.div('.skillbartext',ui.timer); ui.timer.popnode.style.opacity=1; ui.timer.position=4; ui.timer.style.zIndex=5; ui.timer.set=function(text,percentage){ if(typeof text=='string'||typeof text=='number'){ ui.timer.popnode.innerHTML=text; } ui.timer.fillnode.style.top=((1-percentage)*100)+'%'; } var setTimerPosition=function(e){ this.position++; if(this.position>4){ this.position=1; } var left1='180px'; var left2='calc(100% - 245px)'; var top1='210px'; var top2='calc(100% - 245px)'; if(game.layout=='default'){ left1='265px'; top1='160px'; left2='calc(100% - 330px)'; top2='calc(100% - 235px)'; } if(this.position==1||this.position==2){ this.style.top=top2; } else{ this.style.top=top1; } if(this.position==1||this.position==4){ this.style.left=left2; } else{ this.style.left=left1; } } ui.timer.listen(setTimerPosition); ui.shortcut=ui.create.div('#shortcut.hidden',ui.window); ui.shortcut.listen(ui.click.shortcut); ui.create.div(ui.shortcut,function(e){e.stopPropagation()}); ui.create.div('.menubutton.round','重来',ui.shortcut,game.reload).dataset.position=1; ui.create.div('.menubutton.round','退出',ui.shortcut,game.exit).dataset.position=3; ui.create.div('.menubutton.round','记录',ui.shortcut,ui.click.pause).dataset.position=4; ui.shortcut.autobutton=ui.create.div('.menubutton.round','托管',ui.shortcut,ui.click.auto); ui.shortcut.autobutton.dataset.position=2; ui.favmodelist=ui.create.div('.favmodelist',ui.shortcut); ui.favmodelist.update=function(){ const favouriteMode=lib.config.favouriteMode; let removed=false; for(let index=0;indexthis.add(value,index)); let mode=lib.config.mode; const config=get.config(`${mode}_mode`); if(typeof config=='string') mode+=`|${config}`; if(favouriteMode.contains(mode)) ui.favmode.classList.add('glow'); else ui.favmode.classList.remove('glow'); }; ui.favmodelist.add=function(name,index){ const info=name.split('|'),mode=info[0],submode=info[1],node=ui.create.div('.menubutton.large',this),dataset=node.dataset; dataset.type=Math.min(6,lib.config.favouriteMode.length)%2==0?'even':'odd'; dataset.position=index; let str=lib.translate[name]||lib.translate[mode]||''; if(str.length==2) str+='模式'; node.innerHTML=str; node.listen(()=>{ game.saveConfig('mode',mode); if(submode) game.saveConfig(`${mode}_mode`,submode,mode); game.reload(); }); }; ui.favmode=ui.create.system('收藏',function(){ const mode=typeof _status.mode=='string'?`${lib.config.mode}|${_status.mode}`:lib.config.mode; if(this.classList.contains('glow')){ this.classList.remove('glow'); lib.config.favouriteMode.remove(mode); } else{ this.classList.add('glow'); lib.config.favouriteMode.add(mode); } game.saveConfig('favouriteMode',lib.config.favouriteMode); ui.favmodelist.update(); _status.clicked=true; }); ui.favmode.style.display='none'; ui.favmodelist.update(); // ui.create.div('.menubutton.round','菜单',ui.shortcut,ui.click.config).dataset.position=5; if(_status.connectMode){ ui.playerids.remove(); ui.pause.innerHTML='记录'; } setTimerPosition.call(ui.timer); ui.arena.appendChild(ui.timer); if(!game.syncMenu){ lib.onfree.push(function(){ ui.create.menu(); ui.config2.classList.remove('hidden'); ui.roundmenu.classList.remove('transparent2'); setTimeout(function(){ ui.config2.style.transition=''; },500); }); } else{ ui.create.menu(); } lib.status.date=new Date(); lib.status.dateDelayed=0; while(lib.arenaReady.length){ (lib.arenaReady.shift())(); } delete lib.arenaReady; if(lib.config.auto_check_update){ setTimeout(function(){ game.checkForUpdate(false); },3000); } if(!lib.config.asset_version){ lib.onfree.push(function(){ setTimeout(function(){ if(!game.download){ game.saveConfig('asset_version','无'); } else{ var func=function(){ if(confirm('是否下载图片和字体素材?(约175MB)')){ if(!ui.arena.classList.contains('menupaused')){ ui.click.configMenu(); ui.click.menuTab('其它'); } setTimeout(game.checkForAssetUpdate,500); } else{ game.saveConfig('asset_version','无'); } } if(_status.new_tutorial){ _status.new_tutorial=func; } else{ func(); } } },3000); }); } if(localStorage.getItem(lib.configprefix+'playback')){ setTimeout(lib.init.onfree); } if(lib.config.test_game){ ui.window.classList.add('testing'); lib.config.game_speed='vfast'; lib.config.low_performance=true; lib.config.animation=false; _status.auto=true; ui.auto.classList.add('glow'); setTimeout(function(){ var node=ui.create.pause().animate('start'); node.appendChild(ui.sidebar); node.firstChild.innerHTML='正在测试'; node.removeEventListener('click',ui.click.resume); },500); } }, system:function(str,func,right,before){ var parent=right?ui.system2:ui.system1; var node=ui.create.div(); if(before){ parent.insertBefore(node,parent.firstChild); } else{ parent.appendChild(node); } node.innerHTML=str; if(func){ node.listen(func); } if(lib.config.button_press){ node.addEventListener(lib.config.touchscreen?'touchstart':'mousedown',function(e){ if(!node.classList.contains('hidden')) node.classList.add('pressdown'); }); node.addEventListener(lib.config.touchscreen?'touchend':'mouseup',function(e){ node.classList.remove('pressdown'); }); node.addEventListener(lib.config.touchscreen?'touchmove':'mousemove',function(e){ node.classList.remove('pressdown'); }); } return node; }, pause:function(){ if(_status.pausing) return; ui.click.shortcut(false); var node=ui.create.div(".pausedbg",ui.window); _status.pausing=true; setTimeout(function(){ _status.pausing=false; },500); if(lib.config.touchscreen){ setTimeout(function(){ node.addEventListener('touchend',ui.click.resume); },500); } else{ node.addEventListener('click',ui.click.resume); } if(!lib.config.touchscreen){ node.oncontextmenu=ui.click.resume; } var node2=ui.create.div(node); if(_status.connectMode){ node2.innerHTML=''; } else{ node2.innerHTML='已暂停'; } // node2.listen(function(){ // _status.clicked=true; // if(ui.sidebar.classList.contains('hidden')){ // ui.sidebar.show(); // ui.sidebar3.show(); // } // else{ // ui.sidebar.hide(); // ui.sidebar3.hide(); // } // }); return node; }, prebutton:function(item,type,position,noclick){ var node=ui.create.div(position); node.style.display='none'; node.link=item; node.activate=function(){ ui.create.button(item,type,position,noclick,node); delete node.activate; } _status.prebutton.push(node); return node; }, buttonPresets:{ tdnodes:(item,type,position,noclick,node)=>{ node=ui.create.div('.shadowed.reduce_radius.pointerdiv.tdnode.tdnodes',position); if(Array.isArray(item)){ node.innerHTML=''+(item[1])+''; node.link=item[0]; } else{ node.innerHTML=''+(item)+''; node.link=item; } return node; }, blank:(item,type,position,noclick,node)=>{ node=ui.create.div('.button.card',position); node.link=item; return node; }, card:(item,type,position,noclick,node)=>{ if(typeof item.copy=='function'){ node=item.copy(false); } else{ node=item.cloneNode(true); } node.classList.add('button'); if(position) position.appendChild(node); node.link=item; if(item.style.backgroundImage){ node.style.backgroundImage=item.style.backgroundImage; node.style.backgroundSize='cover'; } if(item.style.color){ node.style.color=item.style.color; } if(item.nature){ let natures=get.natureList(item.nature); natures.forEach(n=>node.classList.add(n)); } if(!noclick){ lib.setIntro(node); } if(get.position(item)=='j'&&item.viewAs&&item.viewAs!=item.name&&lib.config.cardtempname!='off'){ ui.create.cardTempName(item,node); } return node; }, vcard:(item,type,position,noclick,node)=>{ if(typeof item=='string'){ item=[get.type(item),'',item]; } node=ui.create.card(position,'noclick',noclick); node.classList.add('button'); node.init(item); node.link=item; return node; }, character:(item,type,position,noclick,node)=>{ if(node){ node.classList.add('button'); node.classList.add('character'); node.style.display=''; } else{ node=ui.create.div('.button.character',position); } node._link=item; if(_status.noReplaceCharacter&&type=='characterx') type='character'; if(type=='characterx'){ if(lib.characterReplace[item]&&lib.characterReplace[item].length) item=lib.characterReplace[item].randomGet(); } node.link=item; var double=get.is.double(node._link,true); if(double) node._changeGroup=true; if(type=='characterx'&&lib.characterReplace[node._link]&&lib.characterReplace[node._link].length>1) node._replaceButton=true; var func=function(node,item){ node.setBackground(item,'character'); if(node.node){ node.node.name.remove(); node.node.hp.remove(); node.node.group.remove(); node.node.intro.remove(); if(node.node.replaceButton) node.node.replaceButton.remove(); } node.node={ name:ui.create.div('.name',node), hp:ui.create.div('.hp',node), group:ui.create.div('.identity',node), intro:ui.create.div('.intro',node), }; var infoitem=lib.character[item]; if(!infoitem){ for(var itemx in lib.characterPack){ if(lib.characterPack[itemx][item]){ infoitem=lib.characterPack[itemx][item];break; } } } node.node.name.innerHTML=get.slimName(item); if(lib.config.buttoncharacter_style=='default'||lib.config.buttoncharacter_style=='simple'){ if(lib.config.buttoncharacter_style=='simple'){ node.node.group.style.display='none'; } node.classList.add('newstyle'); node.node.name.dataset.nature=get.groupnature(get.bordergroup(infoitem)); node.node.group.dataset.nature=get.groupnature(get.bordergroup(infoitem),'raw'); ui.create.div(node.node.hp); var hp=get.infoHp(infoitem[2]),maxHp=get.infoMaxHp(infoitem[2]),hujia=get.infoHujia(infoitem[2]); var str=get.numStr(hp); if(hp!=maxHp){ str+='/'; str+=get.numStr(maxHp); } var textnode=ui.create.div('.text',str,node.node.hp); if(infoitem[2]==0){ node.node.hp.hide(); } else if(get.infoHp(infoitem[2])<=3){ node.node.hp.dataset.condition='mid'; } else{ node.node.hp.dataset.condition='high'; } if(hujia>0){ ui.create.div(node.node.hp,'.shield'); ui.create.div('.text',get.numStr(hujia),node.node.hp); } } else{ var hp=get.infoHp(infoitem[2]); var maxHp=get.infoMaxHp(infoitem[2]); var shield=get.infoHujia(infoitem[2]); if(maxHp>14){ if(typeof infoitem[2]=='string') node.node.hp.innerHTML=infoitem[2]; else node.node.hp.innerHTML=get.numStr(infoitem[2]); node.node.hp.classList.add('text'); } else{ for(var i=0;i=hp) next.classList.add('exclude'); } for(var i=0;i=4){ node.node.name.classList.add('long'); if(lib.config.buttoncharacter_style=='old'){ node.addEventListener('mouseenter',ui.click.buttonnameenter); node.addEventListener('mouseleave',ui.click.buttonnameleave); } } node.node.intro.innerHTML=lib.config.intro; if(!noclick){ lib.setIntro(node); } if(infoitem[1]){ if(double){ node.node.group.innerHTML=double.reduce((previousValue,currentValue)=>`${previousValue}
    ${get.translation(currentValue)}
    `,''); if(double.length>4) if(new Set([5,6,9]).has(double.length)) node.node.group.style.height='48px'; else node.node.group.style.height='64px'; } else node.node.group.innerHTML=`
    ${get.translation(infoitem[1])}
    `; node.node.group.style.backgroundColor=get.translation(`${get.bordergroup(infoitem)}Color`); } else{ node.node.group.style.display='none'; } if(node._replaceButton){ var intro=ui.create.div('.button.replaceButton',node); node.node.replaceButton=intro; intro.innerHTML='切换'; intro._node=node; intro.addEventListener(lib.config.touchscreen?'touchend':'click',function(){ _status.tempNoButton=true; var node=this._node; var list=lib.characterReplace[node._link]; var link=node.link; var index=list.indexOf(link); if(index==list.length-1) index=0; else index++; link=list[index]; node.link=link; node.refresh(node,link); setTimeout(function(){ delete _status.tempNoButton; },200); }); } }; node.refresh=func; node.refresh(node,item); return node; }, characterx:(item,type,position,noclick,node)=>{ return ui.create.buttonPresets.character(item,type,position,noclick,node); }, player:(item,type,position,noclick,node)=>{ if(node){ node.classList.add('button'); node.classList.add('character'); node.style.display=''; } else{ node=ui.create.div('.button.character',position); } node._link=item; node.link=item; node.node={ name:ui.create.div('.name',node), intro:ui.create.div('.intro',node) } if(item.name&&item.name.startsWith('unknown')){ if(item.node&&item.node.name_seat){ node.classList.add('cardbg'); ui.create.div('.avatar_name',node,get.translation(item.name)); } else{ node.setBackground(item.name1,'character'); } } else{ node.setBackground(item.name,'character'); } return node; } }, button:(item,type,position,noClick,button)=>new lib.element.Button(item,type,position,noClick,button), buttons:function(list,type,position,noclick,zoom){ var buttons=[]; var pre=(typeof type=='string'&&type.slice(0,3)=='pre'); if(pre){ if(!_status.prebutton){ _status.prebutton=[]; lib.onfree.push(function(){ for(var i=0;i<_status.prebutton.length;i++){ if(_status.prebutton[i].activate){ _status.prebutton[i].activate(); } } delete _status.prebutton; }); } } for(var i=0;i'; var next=dialog.add(str); if(!noclick) next.firstChild.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.button); next.firstChild.link=link; Object.setPrototypeOf(next,lib.element.Button.prototype); dialog.buttons.add(next.firstChild); } }, player:(position,noclick)=>new lib.element.Player(position,noclick), connectPlayers:ip=>{ ui.updateConnectPlayerPositions(); game.connectPlayers=[]; const numberOfPlayers=lib.configOL.number; for(let position=0;position=numberOfPlayers-1){ alert('至少要有两名玩家才能开始游戏!'); return; } game.resume(); } button.delete(); bar.delete(); delete ui.connectStartButton; delete ui.connectStartBar; button.clicked=true; }); ui.connectStartButton=button; ui.connectStartBar=bar; }, players:numberOfPlayers=>{ if(numberOfPlayers===0){ return; } if(numberOfPlayers==undefined) numberOfPlayers=lib.configOL.number; if(numberOfPlayers==undefined) numberOfPlayers=get.playerNumber(); if(typeof numberOfPlayers=='string'){ numberOfPlayers=parseInt(numberOfPlayers); } if(!numberOfPlayers) numberOfPlayers=5; for(let ordinal=0;ordinal0){ players[ordinal].previous=players[ordinal-1]; players[ordinal].previousSeat=players[ordinal-1]; } if(ordinalui.arena.appendChild(player)); return players; }, me:function(hasme){ ui.mebg=ui.create.div('#mebg',ui.arena); ui.me=ui.create.div('#me',ui.arena).animate('start'); ui.handcards1Container=ui.create.div('#handcards1',ui.me); ui.handcards2Container=ui.create.div('#handcards2',ui.me); ui.arena.classList.remove('nome'); if(lib.config.mousewheel&&!lib.config.touchscreen){ ui.handcards1Container.onmousewheel=ui.click.mousewheel; ui.handcards2Container.onmousewheel=ui.click.mousewheel; } ui.handcards1Container.ontouchstart = ui.click.touchStart; ui.handcards2Container.ontouchstart = ui.click.touchStart; ui.handcards1Container.ontouchmove = ui.click.touchScroll; ui.handcards2Container.ontouchmove = ui.click.touchScroll; ui.handcards1Container.style.webkitOverflowScrolling='touch'; ui.handcards2Container.style.webkitOverflowScrolling='touch'; if(hasme&&game.me){ ui.handcards1=game.me.node.handcards1; ui.handcards2=game.me.node.handcards2; ui.handcards1Container.appendChild(ui.handcards1); ui.handcards2Container.appendChild(ui.handcards2); // ui.updatehl(); } else if(game.players.length){ game.me=game.players[0]; ui.handcards1=game.me.node.handcards1; ui.handcards2=game.me.node.handcards2; ui.handcards1Container.appendChild(ui.handcards1); ui.handcards2Container.appendChild(ui.handcards2); // ui.updatehl(); } }, card:(position,info,noclick)=>new lib.element.Card(position,info,noclick), cardsAsync:function(){ if(lib.onfree){ _status.waitingForCards=Array.from(arguments); lib.onfree.push(function(){ if(_status.waitingForCards){ ui.create.cards.apply(ui.create,_status.waitingForCards); delete _status.waitingForCards; } }); } else{ ui.create.cards.apply(ui.create,arguments); } }, cards:function(ordered){ if(_status.brawl){ if(_status.brawl.cardPile){ lib.card.list=_status.brawl.cardPile(lib.card.list); } if(_status.brawl.orderedPile){ ordered=true; } } if(!ordered){ lib.card.list.randomSort(); } for(var i=0;i'); uiintro.content.lastChild.style.paddingTop=0; button.input=uiintro.content.lastChild.lastChild; button.input.onfocus=function(){ button.focused=true; } button.input.onblur=function(){ delete button.focused; } if(button.interval){ button.input.disabled=true; button.input.style.opacity=0.6; if(button.intervaltext){ button.textnode.innerHTML=button.intervaltext; } } var datenode=ui.create.div(uiintro.content); datenode.style.marginTop=0; datenode.style.whiteSpace='nowrap'; var date=new Date(); var days=[]; var currentDay=date.getDay(); if(currentDay==0) currentDay=7; for(var i=1;i<=7;i++){ if(i7){ initday-=7; } var daysselect=ui.create.selectlist(days,initday.toString(),datenode); daysselect.style.width='55px'; var hours=[]; for(var i=0;i<24;i++){ hours.push([i.toString(),i.toString()+'点']); } var hoursselect=ui.create.selectlist(hours,date.getHours().toString(),datenode); hoursselect.style.marginLeft='5px'; hoursselect.style.width='55px'; var timeconfirm=ui.create.node('button','确定',datenode); timeconfirm.style.marginLeft='5px'; timeconfirm.onclick=function(){ if(!button.input.value){ alert('请填写约战标题'); return; } var date2=new Date(); date2.setHours(parseInt(hoursselect.value)); date2.setMinutes(0); date2.setSeconds(0); var deltaday=parseInt(daysselect.value)-currentDay; if(deltaday<0){ deltaday+=7; } var utc=date2.getTime()+deltaday*24*3600000; if(utcID:'+button.info[i].creator,eventnode); ui.create.div('','已有'+(button.info[i].members.length)+'人加入',eventnode); ui.create.div('','时间:'+str,eventnode); if(button.info[i].members.contains(game.onlineKey)){ eventnode.classList.add('active'); } } else{ ui.create.div('.title',button.info[i].title,eventnode); ui.create.div('',button.info[i].content,eventnode); ui.create.div('','创建者:'+(button.info[i].nickname),eventnode); } } if(num>=3){ button.input.disabled=true; button.input.style.opacity=0.6; hoursselect.disabled=true; daysselect.disabled=true; timeconfirm.disabled=true; } } uiintro.refresh(); ui.window.appendChild(uiintro); _status.connectEventsCallback=function(){ if(uiintro.parentNode==ui.window){ uiintro.refresh(); } }; } }, connectClients:function(){ if(this.info){ var button=this; var layer=ui.create.div('.poplayer',ui.window); var uiintro=ui.create.dialog('hidden','notouchscroll'); this.classList.add('active'); if(lib.config.touchscreen){ lib.setScroll(uiintro.contentContainer); } layer.listen(function(){ if(this.clicked){ this.clicked=false; return; } button.classList.remove('active'); uiintro.delete(); this.delete(); }); uiintro.listen(function(){ _status.clicked=true; }); uiintro.style.zIndex=21; uiintro.classList.add('popped'); uiintro.classList.add('static'); uiintro.classList.add('onlineclient'); uiintro.style.width='180px'; uiintro.style.height='300px'; uiintro.style.left='auto'; uiintro.style.right='20px'; uiintro.style.top='auto'; uiintro.style.bottom='75px'; uiintro.refresh=function(){ if(button.focused) return; uiintro.content.innerHTML=''; uiintro.addText('发状态'); button.textnode=uiintro.content.lastChild.lastChild; uiintro.add(''); uiintro.content.lastChild.style.paddingTop=0; button.input=uiintro.content.lastChild.lastChild; button.input.onfocus=function(){ button.focused=true; } button.input.onblur=function(){ delete button.focused; } if(button.interval){ button.input.disabled=true; button.input.style.opacity=0.6; if(button.intervaltext){ button.textnode.innerHTML=button.intervaltext; } } button.input.onkeydown=function(e){ if(e.keyCode==13&&!this.disabled){ game.send('server','status',this.value); this.blur(); this.disabled=true; this.style.opacity=0.6; button.textnode.innerHTML='发状态(10)'; button.intervaltext=button.textnode.innerHTML; var num=10; var that=this; button.input.disabled=true; button.input.style.opacity=0.6; this.value=''; button.interval=setInterval(function(){ num--; if(num>0){ button.textnode.innerHTML='发状态('+num+')'; button.intervaltext=button.textnode.innerHTML; } else{ button.textnode.innerHTML='发状态'; button.input.disabled=false; button.input.style.opacity=''; clearInterval(button.interval); delete button.interval; delete button.intervaltext; } },1000); } } for(var i=0;i'+(button.info[i][0]||'无名玩家'),node);node.isme=true; } else if(button.info[i][2]){ ui.create.div('.name',(button.info[i][0]||'无名玩家'),node); } else{ ui.create.div('.name',''+(button.info[i][0]||'无名玩家'),node); } //show ID //ui.create.div('.videostatus',node,button.info[i][5]); //node.classList.add('videonodestatus'); if(button.info[i][3]){ ui.create.div('.videostatus',node,button.info[i][3].slice(0,80)); node.classList.add('videonodestatus') } } }; uiintro.refresh(); ui.window.appendChild(uiintro); _status.connectClientsCallback=function(){ if(uiintro.parentNode==ui.window){ uiintro.refresh(); } }; } }, autoskin:function(){ if(!lib.config.change_skin) return; var players=game.filterPlayer(); var change=function(player,num,callback){ if(num=='1'){ ui.click.skin(player.node.avatar,player.name,callback); } else{ ui.click.skin(player.node.avatar2,player.name2,callback); } }; var finish=function(){ if(lib.config.change_skin_auto!='off'){ _status.skintimeout=setTimeout(ui.click.autoskin,parseInt(lib.config.change_skin_auto)); } }; var autoskin=function(){ if(players.length){ var player=players.randomRemove(); var list=[]; if(player.name&&!player.isUnseen(0)){ list.push('1'); } if(player.name2&&!player.isUnseen(1)){ list.push('2'); } if(list.length){ change(player,list.randomRemove(),function(bool){ if(bool){ finish(); } else if(list.length){ change(player,list[0],function(bool){ if(bool){ finish(); } else{ autoskin(); } }); } else{ autoskin(); } }); } else{ autoskin(); } } } autoskin(); }, skin:function(avatar,name,callback){ var num=1; if(name.startsWith('gz_')){ name=name.slice(3); } if(lib.config.skin[name]){ num=lib.config.skin[name]+1; } var fakeavatar=avatar.cloneNode(true); var finish=function(bool){ var player=avatar.parentNode; if(bool){ fakeavatar.style.boxShadow='none'; player.insertBefore(fakeavatar,avatar.nextSibling); setTimeout(function(){ fakeavatar.delete(); },100); } if(bool&&lib.config.animation&&!lib.config.low_performance){ player.$rare(); } if(callback){ callback(bool); } } var img=new Image(); img.onload=function(){ lib.config.skin[name]=num; game.saveConfig('skin',lib.config.skin); avatar.style.backgroundImage='url("'+img.src+'")'; finish(true); } img.onerror=function(){ if(lib.config.skin[name]){ finish(true); } else{ finish(false); } delete lib.config.skin[name]; game.saveConfig('skin',lib.config.skin); avatar.setBackground(name,'character'); } img.src=lib.assetURL+'image/skin/'+name+'/'+num+'.jpg'; }, touchpop:function(forced){ if(lib.config.touchscreen||forced){ _status.touchpopping=true; clearTimeout(_status.touchpoppingtimeout); _status.touchpoppingtimeout=setTimeout(function(){ _status.touchpopping=false; },600); } }, exit:function(){ if(game.servermode&&lib.config.reconnect_info&&_status.over){ if(!_status.roomtimeout){ lib.config.reconnect_info[2]=game.roomId; game.saveConfig('reconnect_info',lib.config.reconnect_info); } game.reload(); return; } else{ if(typeof game.roomId!='string'){ game.saveConfig('reconnect_info'); } } if(!ui.exit||!ui.exit.stay){ if(lib.config.reconnect_info){ lib.config.reconnect_info.length=1; game.saveConfig('reconnect_info',lib.config.reconnect_info); } game.saveConfig('tmp_user_roomId',undefined,false,function(){ game.reload(); }); } else{ game.reload(); } }, shortcut:function(show){ if(show===false){ ui.shortcut.classList.add('hidden'); } else{ ui.shortcut.classList.toggle('hidden'); } if(ui.shortcut.classList.contains('hidden')){ ui.favmode.style.display='none'; if(window.StatusBar&&lib.config.show_statusbar_ios=='auto'){ document.body.classList.remove('statusbar'); window.StatusBar.hide(); } ui.window.classList.remove('shortcutpaused'); } else{ if(lib.config.show_favmode){ ui.favmode.style.display=''; } if(window.StatusBar&&lib.config.show_statusbar_ios=='auto'){ document.body.classList.add('statusbar'); window.StatusBar.overlaysWebView(true); window.StatusBar.backgroundColorByName('black'); window.StatusBar.show(); } if(_status.auto){ ui.shortcut.autobutton.classList.add('active'); } else{ ui.shortcut.autobutton.classList.remove('active'); } ui.window.classList.add('shortcutpaused'); } }, favouriteCharacter:function(e){ if(typeof this.link=='string'){ if(this.innerHTML=='添加收藏'){ this.innerHTML='移除收藏'; lib.config.favouriteCharacter.add(this.link); } else{ this.innerHTML='添加收藏'; lib.config.favouriteCharacter.remove(this.link); } if(ui.favouriteCharacter){ if(lib.config.favouriteCharacter.contains(this.link)){ for(var i=0;i=node.scrollHeight){ clearInterval(that.buttonscrollinterval); delete that.buttonscrollinterval; } else{ if(num>0){ num--; } else{ node.scrollTop+=2; } } },16); } }, buttonnameleave:function(){ if(this.buttonscrollinterval){ clearInterval(this.buttonscrollinterval); } var node=this.node.name; if(node.offsetHeight1&& !this.classList.contains('popped')&& !this.classList.contains('fixed')){ _status.draggingtouchdialog=this; this._dragorigin={ clientX:e.touches[0].clientX, clientY:e.touches[0].clientY, }; if(!this._dragtransform){ this._dragtransform=[0,0]; } this._dragorigintransform=this._dragtransform.slice(0); e.preventDefault(); e.stopPropagation(); } }, identity:function(e){ if(_status.dragged) return; _status.clicked=true; if(!game.getIdentityList) return; if(_status.video) return; if(this.parentNode.forceShown) return; if(!_status.connectMode&&this.parentNode.ai.stratagem_camouflage&&get.config('nei_auto_mark_camouflage')&&game.me.identity=='nei') return; if(_status.clickingidentity){ for(var i=0;i<_status.clickingidentity[1].length;i++){ _status.clickingidentity[1][i].delete(); _status.clickingidentity[1][i].style.transform=''; } if(_status.clickingidentity[0]==this.parentNode){ delete _status.clickingidentity; return; } } var list=game.getIdentityList(this.parentNode); if(!list) return; if(lib.config.mark_identity_style=='click'){ var list2=[]; for(var i in list){ list2.push(i); } list2.push(list2[0]); for(var i=0;i'+num); if(_status.connectMode) return uiintro; uiintro.add('
    轮数 '+game.roundNumber+'    洗牌 '+game.shuffleNumber+'
    '); uiintro.add('
    弃牌堆
    '); if(ui.discardPile.childNodes.length){ var list=[]; for(var i=0;i无'); } return uiintro; }, chat:function(){ ui.system1.classList.add('shown'); ui.system2.classList.add('shown'); var uiintro=ui.create.dialog('hidden'); uiintro.listen(function(e){ e.stopPropagation(); }); var list=ui.create.div('.caption'); if(get.is.phoneLayout()){ list.style.maxHeight='110px'; } else{ list.style.maxHeight='220px'; } list.style.overflow='scroll'; lib.setScroll(list); uiintro.contentContainer.style.overflow='hidden'; var input; var addEntry=function(info,clear){ if(list._chatempty){ list.innerHTML=''; delete list._chatempty; } var node=ui.create.div('.text.chat'); node.innerHTML=info[0]+': '+info[1]; list.appendChild(node); list.scrollTop=list.scrollHeight; uiintro.style.height=uiintro.content.scrollHeight+'px'; } _status.addChatEntry=addEntry; _status.addChatEntry._origin=uiintro; if(lib.chatHistory.length){ for(var i=0;i'); node.style.paddingTop=0; node.style.marginBottom='16px'; input=node.firstChild; input.style.width='calc(100% - 20px)'; input.onchange=function(){ _status.chatValue=input.value; } input.onkeydown=function(e){ if(e.keyCode==13&&input.value){ var player=game.me; var str=input.value; if(!player){ if(game.connectPlayers){ if(game.online){ for(var i=0;i',function(){ emotionTitle.innerHTML=get.translation(this.pack); for(var j=1;j<=lib.emotionList[this.pack];j++){ var emotionButton=ui.create.div('.card.fullskin','',function(){ var player=game.me; if(!player){ if(game.connectPlayers){ if(game.online){ for(var i=0;iui.window.offsetWidth-10){ left=ui.window.offsetWidth-width-10; } uiintro.style.left=left+'px'; uiintro._poppedorigin=this; if(!lib.config.touchscreen){ uiintro.addEventListener('mouseleave',ui.click.leavehoverpopped); } ui.click.shortcut(false); if(uiintro._onopen){ uiintro._onopen(); } if(this._paused2&&!lib.config.touchscreen){ game.pause2(); uiintro.classList.add('static'); var layer=ui.create.div('.poplayer',ui.window); var clicklayer=function(e){ uiintro.delete(); layer.remove(); game.resume2(); e.stopPropagation(); return false; } uiintro.style.zIndex=21; layer.onclick=clicklayer; layer.oncontextmenu=clicklayer; uiintro.addEventListener('mouseleave',clicklayer); uiintro.addEventListener('click',clicklayer); } }, hoverpopped_leave:function(){ this._poppedalready=false; }, leavehoverpopped:function(){ if(_status.dragged) return; if(this.classList.contains('noleave')) return; this.delete(); var button=this._poppedorigin; var uiintro=this; setTimeout(function(){ if(button._uiintro==uiintro){ delete button._uiintro; } },500); }, dierevive:function(){ if(game.me.isDead()){ game.me.revive(Math.max(1,game.me.maxHp)); game.me.draw(2); } else{ if(ui.revive){ ui.revive.close(); delete ui.revive; } } }, dieswap:function(){ if(game.me.isDead()){ _status.clicked=true; var i,translation,intro,str; if(ui.intro){ ui.intro.close(); if(ui.intro.source=='dieswap'){ delete ui.intro; ui.control.show(); game.resume2(); return; } } game.pause2(); ui.control.hide(); ui.intro=ui.create.dialog(); ui.intro.source='dieswap'; var players=[]; for(var i=0;i100){ if(ui.roundmenu._resetTimeout){ clearTimeout(ui.roundmenu._resetTimeout); delete ui.roundmenu._resetTimeout; } } ui.roundmenu._dragtouches=e.touches[0]; ui.click.checkroundtranslate(translate); } _status.clicked=true; } else if(_status.draggingtouchdialog){ delete _status._swipeorigin; if(_status.draggingtouchdialog._dragorigin&&_status.draggingtouchdialog._dragtransform&&e.touches.length){ var translate=_status.draggingtouchdialog._dragtransform.slice(0); var dx=e.touches[0].clientX/game.documentZoom-_status.draggingtouchdialog._dragorigin.clientX/game.documentZoom; var dy=e.touches[0].clientY/game.documentZoom-_status.draggingtouchdialog._dragorigin.clientY/game.documentZoom; translate[0]+=dx; translate[1]+=dy; _status.draggingtouchdialog._dragtouches=e.touches[0]; ui.click.checkdialogtranslate(translate,_status.draggingtouchdialog); } _status.clicked=true; } else if(_status._swipeorigin&&e.touches[0]){ _status._swipeorigin.touches=e.touches[0]; } if(_status.mousedragging&&e.touches.length){ e.preventDefault(); var item=document.elementFromPoint(e.touches[0].clientX,e.touches[0].clientY); if(game.chess&&ui.selected.cards.length){ var itemtype=get.itemtype(item); if(itemtype!='card'&&itemtype!='button'){ var ex=e.touches[0].clientX/game.documentZoom-ui.arena.offsetLeft; var ey=e.touches[0].clientY/game.documentZoom-ui.arena.offsetTop; for(var i=0;ileft&&extop&&eyitem.offsetLeft&&exitem.offsetTop&&ey=0){ if(dy<=0){ deg+=90; } else{ deg=90-deg; } } else{ if(dy<=0){ deg=270-deg; } else{ deg+=270; } } node.style.transform='rotate('+(-deg)+'deg) scaleY(0)'; node.style.height=get.xyDistance(from,to)+'px'; if(game.chess){ ui.chess.appendChild(node); } else{ ui.arena.appendChild(node); } ui.refresh(node); node.show(); node.style.transform='rotate('+(-deg)+'deg) scaleY(1)'; ui.touchlines.push(node); node._origin=item; } } } else{ _status.lastdragchange.remove(item); for(var i=0;i200){ goswipe(lib.config.swipe_down); } } else if(Math.abs(dy)<100){ if(dx<-200){ goswipe(lib.config.swipe_left); } else if(dx>200){ goswipe(lib.config.swipe_right); } } } } var tmpflag=false; _status.mousedown=false; _status.clicked=false; if(_status.mousedragging&&_status.mouseleft){ if(game.check()){ if(ui.confirm){ ui.confirm.close(); } var event=_status.event; if(!event.filterOk||event.filterOk()) ui.click.ok(); ui.canvas.width=ui.arena.offsetWidth; ui.canvas.height=ui.arena.offsetHeight; } else{ game.uncheck(); game.check(); } } else if(_status.mousedragging&&_status.mousedragorigin){ tmpflag=_status.mousedragorigin; } _status.lastdragchange.length=0; _status.mousedragging=null; _status.mouseleft=false; _status.mousedragorigin=null; _status.dragstatuschanged=false; while(ui.touchlines.length){ ui.touchlines.shift().delete(); } if(tmpflag){ game.check(); } _status.dragged=false; _status.clicked=false; }, checkroundtranslate:function(translate){ var translate=translate||ui.roundmenu._dragtransform; if(translate[1]+ui.roundmenu._position[1]+50+ui.arena.offsetTop>ui.window.offsetHeight){ translate[1]=ui.window.offsetHeight-(ui.roundmenu._position[1]+50)-ui.arena.offsetTop; } else if(translate[1]+ui.roundmenu._position[1]+ui.arena.offsetTop<0){ translate[1]=-ui.roundmenu._position[1]-ui.arena.offsetTop; } if(translate[0]+ui.roundmenu._position[0]+50+ui.arena.offsetLeft>ui.window.offsetWidth){ translate[0]=ui.window.offsetWidth-(ui.roundmenu._position[0]+50)-ui.arena.offsetLeft; } else if(translate[0]+ui.roundmenu._position[0]+ui.arena.offsetLeft<0){ translate[0]=-ui.roundmenu._position[0]-ui.arena.offsetLeft; } ui.roundmenu.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)'; }, checkdialogtranslate:function(translate,dialog){ var translate=translate||dialog._dragtransform; if(Math.sqrt(translate[0]*translate[0]+translate[1]*translate[1])<10){ translate[0]=0; translate[1]=0; } dialog.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)'; }, windowmousewheel:function(e){ _status.tempunpopup=e; }, windowmousemove:function(e){ if(window.inSplash) return; if(_status.tempunpopup){ if(get.evtDistance(_status.tempunpopup,e)>5){ delete _status.tempunpopup; } } if(e.button==2) return; var dialogs=document.querySelectorAll('#window>.dialog.popped:not(.static)'); for(var i=0;ileft&&extop&&eyitem.offsetLeft&&exitem.offsetTop&&ey.dialog.popped:not(.static)'); for(var i=0;ilib.versionOL){ alert('加入失败:你的游戏版本过低'); } else{ alert('加入失败:房主的游戏版本过低'); } } else{ if(!_status.enteringroom){ _status.enteringroom=true; _status.enteringroomserver=this.serving; game.send('server','enter',this.key,get.connectNickname(),lib.config.connect_avatar); } } }, player:function(){ return ui.click.target.apply(this,arguments); }, target:function(e){ if(_status.dragged) return; if(_status.clicked) return; if(ui.intro) return; if(this.classList.contains('connect')){ if(game.online){ if(game.onlinezhu){ if(!this.playerid&&game.connectPlayers){ if(lib.configOL.mode=='versus'||lib.configOL.mode=='doudizhu') return; if(lib.configOL.mode=='identity'&&lib.configOL.identity_mode=='zhong') return; if(!this.classList.contains('unselectable2')&&lib.configOL.number<=2) return; this.classList.toggle('unselectable2') if(this.classList.contains('unselectable2')){ lib.configOL.number--; } else{ lib.configOL.number++; } game.send('changeNumConfig',lib.configOL.number, game.connectPlayers.indexOf(this),this.classList.contains('unselectable2')); } } return; } if(this.playerid){ if(this.ws){ if(confirm('是否踢出'+this.nickname+'?')){ var id=get.id(); this.ws.send(function(id){ if(game.ws){ game.ws.close(); game.saveConfig('reconnect_info'); game.saveConfig('banned_info',id); } },id); lib.node.banned.push(id); } } } else{ if(lib.configOL.mode=='versus'||lib.configOL.mode=='doudizhu'||lib.configOL.mode=='single') return; if(lib.configOL.mode=='identity'&&(lib.configOL.identity_mode=='zhong'||lib.configOL.identity_mode=='purple')) return; if(!this.classList.contains('unselectable2')&&lib.configOL.number<=2) return; this.classList.toggle('unselectable2') if(this.classList.contains('unselectable2')){ lib.configOL.number--; } else{ lib.configOL.number++; } game.send('server','config',lib.configOL); game.updateWaiting(); } return; } _status.clicked=true; var custom=_status.event.custom; if(custom&&custom.replace.target){ custom.replace.target(this,e); return; } if(this.classList.contains('selectable')==false) return; this.unprompt(); if(this.classList.contains('selected')){ ui.selected.targets.remove(this); if(_status.multitarget||_status.event.complexSelect){ game.uncheck(); game.check(); } else{ this.classList.remove('selected'); } } else{ ui.selected.targets.add(this); if(_status.event.name=='chooseTarget'||_status.event.name=='chooseToUse'||_status.event.name=='chooseCardTarget'){ var targetprompt=null; if(_status.event.targetprompt){ targetprompt=_status.event.targetprompt; } else if(_status.event.skill&&!get.info(_status.event.skill).viewAs){ targetprompt=get.info(_status.event.skill).targetprompt; } else if(_status.event.name=='chooseToUse'){ var currentcard=get.card(); if(currentcard){ targetprompt=get.info(currentcard).targetprompt; } } if(targetprompt){ if(Array.isArray(targetprompt)){ targetprompt=targetprompt[Math.min(targetprompt.length-1,ui.selected.targets.indexOf(this))]; } else if(typeof targetprompt=='function'){ targetprompt=targetprompt(this); } if(targetprompt&&typeof targetprompt=='string'){ this.prompt(targetprompt); } } } this.classList.add('selected'); } if(custom.add.target){ custom.add.target(); } game.check(); }, control2:function(){ if(this.childNodes.length==1&&!this._doubleclick){ ui.click.control.call(this.firstChild); } }, control:function(){ if(_status.dragged) return; if(ui.control.classList.contains('hidden')) return; var node=this.parentNode; if(node){ if(node._doubleclick){ return; } else{ node._doubleclick=true; setTimeout(function(){ node._doubleclick=false; },500); } if(node.classList.contains('hidden')) return; if(node.classList.contains('removing')) return; if(node.classList.contains('disabled')) return; } if(ui.intro){ ui.intro.close(); delete ui.intro; } _status.clicked=true; if(this.parentNode.custom){ this.parentNode.custom(this.link,this); return; } if(this.link=='ok'){ ui.click.ok(this); } else if(this.link=='cancel'){ ui.click.cancel(this); } else{ _status.event.result={ buttons:ui.selected.buttons.slice(0), cards:ui.selected.cards.slice(0), targets:ui.selected.targets.slice(0), control:this.link, links:get.links(ui.selected.buttons) }; if(this.parentNode.close!=false){ game.uncheck(); this.parentNode.close(); } game.resume(); } }, dialogcontrol:function(){ _status.event.result={ buttons:ui.selected.buttons.slice(0), cards:ui.selected.cards.slice(0), targets:ui.selected.targets.slice(0), control:this.link, links:get.links(ui.selected.buttons) }; game.resume(); }, skill:function(skill){ var info=get.info(skill); var event=_status.event; event.backup(skill); if(info.filterCard&&info.discard!=false&&info.lose!=false&&!info.viewAs){ var cards=event.player.getCards(event.position); for(var i=0;i
    '+str2+'
    '); if(info.longprompt){ event.skillDialog.forcebutton=true; ui.update(); } } else if(info.promptfunc){ event.skillDialog=ui.create.dialog(str,'
    '+info.promptfunc(event,event.player)+'
    '); } else if(lib.dynamicTranslate[skill]){ event.skillDialog=ui.create.dialog(str,'
    '+lib.dynamicTranslate[skill](event.player,skill)+'
    '); } else if(lib.translate[skill+'_info']){ event.skillDialog=ui.create.dialog(str,'
    '+lib.translate[skill+'_info']+'
    '); } } }, ok:node=>{ const gameEvent=get.event(),custom=gameEvent.custom,replaceConfirm=custom.replace.confirm; if(replaceConfirm){ replaceConfirm(true); return; } const result=gameEvent.result={ buttons:ui.selected.buttons.slice(), cards:ui.selected.cards.slice(), targets:ui.selected.targets.slice(), confirm:'ok', bool:true, links:get.links(ui.selected.buttons) }; if(node) node.parentNode.close(); const skill=gameEvent.skill; if(skill){ result.skill=skill; const skillInformation=get.info(gameEvent.skill),viewAs=skillInformation.viewAs; if(typeof viewAs=='function'){ const viewedAs=viewAs(result.cards,gameEvent.player); if(viewedAs) result.card=get.autoViewAs(viewedAs); } else if(viewAs) result.card=get.autoViewAs(viewAs); const resultCard=result.card; if(resultCard){ const cards=result.cards; if(cards.length==1){ const firstCard=cards[0]; if(!resultCard.suit) resultCard.suit=get.suit(firstCard); if(!resultCard.number) resultCard.number=get.number(firstCard); } } const skillDialog=gameEvent.skillDialog; if(skillDialog&&get.objtype(skillDialog)=='div') skillDialog.close(); gameEvent.player.getCards('hej').forEach(card=>card.recheck('useSkill')); gameEvent.restore(); } else if(['chooseToUse','chooseToRespond'].includes(gameEvent.name)) result.card=get.autoViewAs(result.cards[0]); if(ui.skills) ui.skills.close(); if(ui.skills2) ui.skills2.close(); if(ui.skills3) ui.skills3.close(); game.uncheck(); const addConfirm=custom.add.confirm; if(addConfirm) addConfirm(true); game.resume(); }, cancel:function(node){ var event=_status.event; if(event.custom.replace.confirm){ event.custom.replace.confirm(false);return; } if(event.skill&&!event.norestore){ if(event.skillDialog&&get.objtype(event.skillDialog)=='div'){ event.skillDialog.close(); } if(typeof event.dialog=='string'&&event.isMine()){ event.dialog=ui.create.dialog(event.dialog); } if(_status.event.type=='phase'&&ui.confirm){ ui.confirm.classList.add('removing'); } // ui.control.animate('nozoom',100); event.restore(); var cards=event.player.getCards('hej'); for(var i=0;i=4){ avatars.classList.add('scroll'); if(lib.config.touchscreen){ lib.setScroll(avatars); } } for(var i=0;i<=num;i++){ var button=ui.create.div(avatars,function(){ playerbg.classList.remove('scroll'); if(this._link){ lib.config.skin[nameskin]=this._link; bg.style.backgroundImage=this.style.backgroundImage; if(sourcenode) sourcenode.style.backgroundImage=this.style.backgroundImage; if(avatar) avatar.style.backgroundImage=this.style.backgroundImage; game.saveConfig('skin',lib.config.skin); } else{ delete lib.config.skin[nameskin]; if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin){ bg.setBackground(nameskin2,'character'); if(sourcenode) sourcenode.setBackground(nameskin2,'character'); if(avatar) avatar.setBackground(nameskin2,'character'); } else{ bg.setBackground(nameskin,'character'); if(sourcenode) sourcenode.setBackground(nameskin,'character'); if(avatar) avatar.setBackground(nameskin,'character'); } game.saveConfig('skin',lib.config.skin); } }); button._link=i; if(i){ button.setBackgroundImage('image/skin/'+nameskin+'/'+i+'.jpg'); } else{ if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) button.setBackground(nameskin2,'character','noskin'); else button.setBackground(nameskin,'character','noskin'); } } }; var num=1; var loadImage=function(){ var img=new Image(); img.onload=function(){ num++; loadImage(); } img.onerror=function(){ num--; createButtons(num); } img.src=lib.assetURL+'image/skin/'+nameskin+'/'+num+'.jpg'; } if(lib.config.change_skin){ loadImage(); } else{ createButtons(lib.skin[nameskin]); } }; }; if(lib.config.change_skin){ var img=new Image(); img.onload=changeskin; img.src=lib.assetURL+'image/skin/'+nameskin+'/1.jpg'; } else if(lib.config.debug&&lib.skin[nameskin]){ changeskin(); } var ban=ui.create.div('.menubutton.large.ban.character',uiintro,'禁用',function(e){ if(this.classList.contains('unselectable')) return; if(typeof noedit=='string'){ this.classList.toggle('active'); var bannedname=noedit+'_banned'; if(!lib.config[bannedname]){ lib.config[bannedname]=[]; } if(this.classList.contains('active')){ lib.config[bannedname].add(name); } else{ lib.config[bannedname].remove(name); } game.saveConfig(bannedname,lib.config[bannedname]); ban.updateBanned(); } else{ ui.click.touchpop(); ui.click.intro.call(this,e); _status.clicked=true; } }); ban.link=name; ban._banning='offline'; ban.updateBanned=function(){ if(noedit===true) return; if(lib.config[get.mode()+'_banned']&&lib.config[get.mode()+'_banned'].contains(name)){ ban.classList.add('active'); } else{ ban.classList.remove('active'); } if(sourcenode&&sourcenode.updateBanned){ sourcenode.updateBanned(); } }; ban.updateBanned(); var fav=ui.create.div('.menubutton.large.fav',uiintro,'收藏',function(){ if(this.classList.contains('unselectable')) return; this.classList.toggle('active'); if(this.classList.contains('active')){ lib.config.favouriteCharacter.add(name); } else{ lib.config.favouriteCharacter.remove(name); } game.saveConfig('favouriteCharacter',lib.config.favouriteCharacter); }); if(noedit===true){ fav.classList.add('unselectable'); ban.classList.add('unselectable'); } else if(lib.config.favouriteCharacter.contains(name)){ fav.classList.add('active'); } // 样式二 if(lib.config.show_characternamepinyin=='showPinyin2'||lib.config.show_skillnamepinyin=='showPinyin2'||lib.config.show_characternamepinyin=='showCodeIdentifier2'||lib.config.show_skillnamepinyin=='showCodeIdentifier2'){ var intro=ui.create.div('.characterintro',get.characterIntro(name),uiintro); if(lib.config.show_characternamepinyin=='showPinyin2'||lib.config.show_characternamepinyin=='showCodeIdentifier2'){ var charactername=get.rawName2(name); var characterpinyin=lib.config.show_characternamepinyin=='showCodeIdentifier2'?name:get.pinyin(charactername); var nameinfo=get.character(name); var charactersex=get.translation(nameinfo[0]); const charactergroups=get.is.double(name,true); let charactergroup; if(charactergroups) charactergroup=charactergroups.map(i=>get.translation(i)).join('/') else charactergroup=get.translation(nameinfo[1]); var characterhp=nameinfo[2]; var characterintroinfo=get.characterIntro(name); var spacemark=' | '; if(charactername.length>3) spacemark=''+' '+''+'|'+''+' '+''; intro.innerHTML=''+charactername+''+''+'['+characterpinyin+']'+''+spacemark+charactersex+spacemark+charactergroup+spacemark+characterhp+''+'
    '+characterintroinfo; } var intro2=ui.create.div('.characterintro.intro2',uiintro); var list=get.character(name,3)||[]; var skills=ui.create.div('.characterskill',uiintro); if(lib.config.touchscreen){ lib.setScroll(intro); lib.setScroll(intro2); lib.setScroll(skills); } if(lib.config.mousewheel){ skills.onmousewheel=ui.click.mousewheel; } var clickSkill=function(e){ while(intro2.firstChild){ intro2.removeChild(intro2.lastChild); } var current=this.parentNode.querySelector('.active'); if(current){ current.classList.remove('active'); } this.classList.add('active'); var skillname=get.translation(this.link); var skilltranslationinfo=get.skillInfoTranslation(this.link); if((lib.config.show_skillnamepinyin=='showPinyin2'||lib.config.show_skillnamepinyin=='showCodeIdentifier2')&&skillname!='阵亡'){ var skillpinyin=lib.config.show_skillnamepinyin=='showCodeIdentifier2'?this.link:get.pinyin(skillname); intro2.innerHTML=''+skillname+''+''+'['+skillpinyin+']'+''+' '+skilltranslationinfo; }else{ intro2.innerHTML=''+skillname+''+skilltranslationinfo; } var info=get.info(this.link); var skill=this.link; var playername=this.linkname; var skillnode=this; if(info.derivation){ var derivation=info.derivation; if(typeof derivation=='string'){ derivation=[derivation]; } for(var i=0;i'+''+'['+derivationpinyin+']'+''+' '+derivationtranslationinfo; }else{ intro2.innerHTML+='

    '+derivationname+''+derivationtranslationinfo; } } } if(info.alter){ intro2.innerHTML+='

    '; var skillversionnode=intro2.querySelector('.hrefnode.skillversion'); if(lib.config.vintageSkills.contains(skill)){ skillversionnode.innerHTML='切换至新版'; } else{ skillversionnode.innerHTML='切换至旧版'; } skillversionnode.listen(function(){ if(lib.config.vintageSkills.contains(skill)){ lib.config.vintageSkills.remove(skill); lib.translate[skill+'_info']=lib.translate[skill+'_info_alter']; } else{ lib.config.vintageSkills.push(skill); lib.translate[skill+'_info']=lib.translate[skill+'_info_origin']; } game.saveConfig('vintageSkills',lib.config.vintageSkills); clickSkill.call(skillnode,'init'); }); } // if(e!=='init') game.trySkillAudio(this.link,playername); // 有bug,先用旧版 if(lib.config.background_speak&&e!=='init'){ var audioname=this.link; if(info.audioname2&&info.audioname2[playername]){ audioname=info.audioname2[playername]; info=lib.skill[audioname]; } var audioinfo=info.audio; var that=this; var getIndex=function(i){ if(typeof that.audioindex!='number'){ that.audioindex=i; } that.audioindex++; if(that.audioindex>i){ that.audioindex=1; } return that.audioindex; }; if(typeof audioinfo=='string'){ if(audioinfo.indexOf('ext:')==0){ audioinfo=audioinfo.split(':'); if(audioinfo.length==3){ if(audioinfo[2]=='true'){ game.playAudio('..','extension',audioinfo[1],audioname); } else{ audioinfo[2]=parseInt(audioinfo[2]); if(audioinfo[2]){ game.playAudio('..','extension',audioinfo[1],audioname+getIndex(audioinfo[2])); } } } return; } else{ audioname=audioinfo; if(lib.skill[audioinfo]){ audioinfo=lib.skill[audioinfo].audio; } } } else if(Array.isArray(audioinfo)){ audioname=audioinfo[0]; audioinfo=audioinfo[1]; } if(typeof audioinfo=='number'){ if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername; game.playAudio('skill',audioname+getIndex(audioinfo)); } else if(typeof audioinfo=="object"&&"type" in audioinfo&&audioinfo.type=="direct"&&"files" in audioinfo){ let audioFiles=audioinfo.files; if(typeof audioFiles=="object"){ if(!Array.isArray(audioFiles)&&playername&&playername in audioFiles)audioFiles=audioFiles[playername]; if(Array.isArray(audioFiles)){ const length=audioFiles.length; game.playAudio(audioFiles[getIndex(length)-1]); } } } else if(audioinfo){ if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername; game.playAudio('skill',audioname); } else if(true&&info.audio!==false){ if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername; game.playSkillAudio(audioname,getIndex(2)); } } } }else{ // 样式一 const introduction=ui.create.div('.characterintro',uiintro),showCharacterNamePinyin=lib.config.show_characternamepinyin; if(showCharacterNamePinyin!='doNotShow'){ const characterIntroTable=ui.create.div('.character-intro-table',introduction),span=document.createElement('span'); span.style.fontWeight='bold'; const nameInfo=get.character(name),exInfo=nameInfo[4],characterName=exInfo&&exInfo.includes('ruby')?lib.translate[name]:get.rawName2(name); span.innerHTML=characterName; const ruby=document.createElement('ruby'); ruby.appendChild(span); const leftParenthesisRP=document.createElement('rp'); leftParenthesisRP.textContent='('; ruby.appendChild(leftParenthesisRP); const rt=document.createElement('rt'); rt.innerHTML=showCharacterNamePinyin=='showCodeIdentifier'?name:lib.translate[`${name}_rt`]||get.pinyin(characterName).join(' '); ruby.appendChild(rt); const rightParenthesisRP=document.createElement('rp'); rightParenthesisRP.textContent=')'; ruby.appendChild(rightParenthesisRP); characterIntroTable.appendChild(ruby); const characterSexDiv=ui.create.div('.character-sex',characterIntroTable),exInfoSex=exInfo&&exInfo.find(value=>value.startsWith('sex:')),characterSex=exInfoSex?exInfoSex.split(':').pop():nameInfo[0]; new Promise((resolve,reject)=>{ const imageName=`sex_${characterSex}`,information=lib.card[imageName]; if(!information) { resolve(`${lib.assetURL}image/card/${imageName}.png`) return; }; const image=information.image; if(!image) resolve(`${lib.assetURL}image/card/${imageName}.png`); else if(image.startsWith('db:')) game.getDB('image',image.slice(3)).then(resolve,reject); else if(image.startsWith('ext:')) resolve(`${lib.assetURL}${image.replace(/^ext:/,'extension/')}`); else resolve(`${lib.assetURL}${image}`); }).then(source=>new Promise((resolve,reject)=>{ const image=new Image(); image.onload=()=>resolve(image); image.onerror=reject; image.src=source; })).then(image=>characterSexDiv.appendChild(image)).catch(()=>characterSexDiv.innerHTML=get.translation(characterSex)); const characterGroupDiv=ui.create.div('.character-group',characterIntroTable),characterGroups=get.is.double(name,true); if(characterGroups) Promise.all(characterGroups.map(characterGroup=>new Promise((resolve,reject)=>{ const imageName=`group_${characterGroup}`,information=lib.card[imageName]; if(!information) resolve(`${lib.assetURL}image/card/${imageName}.png`); const image=information.image; if(!image) resolve(`${lib.assetURL}image/card/${imageName}.png`); else if(image.startsWith('db:')) game.getDB('image',image.slice(3)).then(resolve,reject); else if(image.startsWith('ext:')) resolve(`${lib.assetURL}${image.replace(/^ext:/,'extension/')}`); else resolve(`${lib.assetURL}${image}`); }).then(source=>new Promise((resolve,reject)=>{ const image=new Image(); image.onload=()=>resolve(image); image.onerror=reject; image.src=source; })))).then(images=>{ let documentFragment=document.createDocumentFragment(); images.forEach(documentFragment.appendChild,documentFragment); characterGroupDiv.appendChild(documentFragment); }).catch(()=>characterGroupDiv.innerHTML=characterGroups.map(characterGroup=>get.translation(characterGroup)).join('/')); else{ const characterGroup=nameInfo[1]; new Promise((resolve,reject)=>{ const imageName=`group_${characterGroup}`,information=lib.card[imageName]; if(!information) resolve(`${lib.assetURL}image/card/${imageName}.png`); const image=information.image; if(!image) resolve(`${lib.assetURL}image/card/${imageName}.png`); else if(image.startsWith('db:')) game.getDB('image',image.slice(3)).then(resolve,reject); else if(image.startsWith('ext:')) resolve(`${lib.assetURL}${image.replace(/^ext:/,'extension/')}`); else resolve(`${lib.assetURL}${image}`); }).then(source=>new Promise((resolve,reject)=>{ const image=new Image(); image.onload=()=>resolve(image); image.onerror=reject; image.src=source; })).then(image=>characterGroupDiv.appendChild(image)).catch(()=>characterGroupDiv.innerHTML=get.translation(characterGroup)); } const hpDiv=ui.create.div('.hp',characterIntroTable),nameInfoHP=nameInfo[2],infoHP=get.infoHp(nameInfoHP); hpDiv.dataset.condition=infoHP<4?'mid':'high'; ui.create.div(hpDiv); const hpTextDiv=ui.create.div('.text',hpDiv),infoMaxHP=get.infoMaxHp(nameInfoHP); hpTextDiv.innerHTML=infoHP==infoMaxHP?`×${infoHP}`:`×${infoHP}/${infoMaxHP}`; const infoShield=get.infoHujia(nameInfoHP); if(infoShield){ ui.create.div('.shield',hpDiv); const shieldTextDiv=ui.create.div('.text',hpDiv); shieldTextDiv.innerHTML=`×${infoShield}`; } introduction.appendChild(document.createElement('hr')); } const htmlParser=document.createElement('body'); htmlParser.innerHTML=get.characterIntro(name); Array.from(htmlParser.childNodes).forEach(value=>introduction.appendChild(value)); const introduction2=ui.create.div('.characterintro.intro2',uiintro); var list=get.character(name,3)||[]; var skills=ui.create.div('.characterskill',uiintro); if(lib.config.touchscreen){ lib.setScroll(introduction); lib.setScroll(introduction2); lib.setScroll(skills); } if(lib.config.mousewheel){ skills.onmousewheel=ui.click.mousewheel; } var clickSkill=function(e){ while(introduction2.firstChild){ introduction2.removeChild(introduction2.lastChild); } var current=this.parentNode.querySelector('.active'); if(current){ current.classList.remove('active'); } this.classList.add('active'); const skillNameSpan=document.createElement('span'),skillNameSpanStyle=skillNameSpan.style; skillNameSpanStyle.fontWeight='bold'; const link=this.link,skillName=get.translation(link); skillNameSpan.innerHTML=skillName; const showSkillNamePinyin=lib.config.show_skillnamepinyin; if(showSkillNamePinyin!='doNotShow'&&skillName!='阵亡'){ const ruby=document.createElement('ruby'); ruby.appendChild(skillNameSpan); const leftParenthesisRP=document.createElement('rp'); leftParenthesisRP.textContent='('; ruby.appendChild(leftParenthesisRP); const rt=document.createElement('rt'); rt.innerHTML=showSkillNamePinyin=='showCodeIdentifier'?link:lib.translate[`${link}_rt`]||get.pinyin(skillName).join(' '); ruby.appendChild(rt); const rightParenthesisRP=document.createElement('rp'); rightParenthesisRP.textContent=')'; ruby.appendChild(rightParenthesisRP); const div=ui.create.div(introduction2); div.style.marginRight='5px'; div.appendChild(ruby); } else{ skillNameSpanStyle.marginRight='5px'; introduction2.appendChild(skillNameSpan); } htmlParser.innerHTML=get.skillInfoTranslation(this.link); Array.from(htmlParser.childNodes).forEach(childNode=>introduction2.appendChild(childNode)); var info=get.info(this.link); var skill=this.link; var playername=this.linkname; var skillnode=this; let derivations=info.derivation; if(derivations){ if(typeof derivations=='string') derivations=[derivations]; derivations.forEach(derivation=>{ introduction2.appendChild(document.createElement('br')); introduction2.appendChild(document.createElement('br')); const derivationNameSpan=document.createElement('span'),derivationNameSpanStyle=derivationNameSpan.style; derivationNameSpanStyle.fontWeight='bold'; const derivationName=get.translation(derivation); derivationNameSpan.innerHTML=derivationName; if(showSkillNamePinyin!='doNotShow'&&derivationName.length<=5&&derivation.indexOf('_faq')==-1){ const ruby=document.createElement('ruby'); ruby.appendChild(derivationNameSpan); const leftParenthesisRP=document.createElement('rp'); leftParenthesisRP.textContent='('; ruby.appendChild(leftParenthesisRP); const rt=document.createElement('rt'); rt.innerHTML=showSkillNamePinyin=='showCodeIdentifier'?derivation:lib.translate[`${derivation}_rt`]||get.pinyin(derivationName).join(' '); ruby.appendChild(rt); const rightParenthesisRP=document.createElement('rp'); rightParenthesisRP.textContent=')'; ruby.appendChild(rightParenthesisRP); const div=ui.create.div(introduction2); div.style.marginRight='5px'; div.appendChild(ruby); } else{ derivationNameSpanStyle.marginRight='5px'; introduction2.appendChild(derivationNameSpan); } htmlParser.innerHTML=get.skillInfoTranslation(derivation); Array.from(htmlParser.childNodes).forEach(childNode=>introduction2.appendChild(childNode)); }); } if(info.alter){ introduction2.appendChild(document.createElement('br')); introduction2.appendChild(document.createElement('br')); ui.create.div('.hrefnode.skillversion',introduction2); var skillversionnode=introduction2.querySelector('.hrefnode.skillversion'); if(lib.config.vintageSkills.contains(skill)){ skillversionnode.innerHTML='切换至新版'; } else{ skillversionnode.innerHTML='切换至旧版'; } skillversionnode.listen(function(){ if(lib.config.vintageSkills.contains(skill)){ lib.config.vintageSkills.remove(skill); lib.translate[skill+'_info']=lib.translate[skill+'_info_alter']; } else{ lib.config.vintageSkills.push(skill); lib.translate[skill+'_info']=lib.translate[skill+'_info_origin']; } game.saveConfig('vintageSkills',lib.config.vintageSkills); clickSkill.call(skillnode,'init'); }); } // if(e!=='init') game.trySkillAudio(this.link,playername); // 有bug,先用旧版 if(lib.config.background_speak&&e!=='init'){ var audioname=this.link; if(info.audioname2&&info.audioname2[playername]){ audioname=info.audioname2[playername]; info=lib.skill[audioname]; } var audioinfo=info.audio; var that=this; var getIndex=function(i){ if(typeof that.audioindex!='number'){ that.audioindex=i; } that.audioindex++; if(that.audioindex>i){ that.audioindex=1; } return that.audioindex; }; if(typeof audioinfo=='string'){ if(audioinfo.indexOf('ext:')==0){ audioinfo=audioinfo.split(':'); if(audioinfo.length==3){ if(audioinfo[2]=='true'){ game.playAudio('..','extension',audioinfo[1],audioname); } else{ audioinfo[2]=parseInt(audioinfo[2]); if(audioinfo[2]){ game.playAudio('..','extension',audioinfo[1],audioname+getIndex(audioinfo[2])); } } } return; } else{ audioname=audioinfo; if(lib.skill[audioinfo]){ audioinfo=lib.skill[audioinfo].audio; } } } else if(Array.isArray(audioinfo)){ audioname=audioinfo[0]; audioinfo=audioinfo[1]; } if(typeof audioinfo=='number'){ if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername; game.playAudio('skill',audioname+getIndex(audioinfo)); } else if(typeof audioinfo=="object"&&"type" in audioinfo&&audioinfo.type=="direct"&&"files" in audioinfo){ let audioFiles=audioinfo.files; if(typeof audioFiles=="object"){ if(!Array.isArray(audioFiles)&&playername&&playername in audioFiles)audioFiles=audioFiles[playername]; if(Array.isArray(audioFiles)){ const length=audioFiles.length; game.playAudio(audioFiles[getIndex(length)-1]); } } } else if(audioinfo){ if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername; game.playAudio('skill',audioname); } else if(true&&info.audio!==false){ if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername; game.playSkillAudio(audioname,getIndex(2)); } } } } var initskill=false; for(var i=0;i 0 || evt.wheelDelta < 0){ node.interval=setInterval(function(){ if(num--&&Math.abs(node.scrollLeft+node.clientWidth-node.scrollWidth)>0){ node.scrollLeft +=speed; } else{ clearInterval(node.interval); } },16); } else{ node.interval=setInterval(function(){ if(num--&&node.scrollLeft>0){ node.scrollLeft -=speed; } else{ clearInterval(node.interval); } },16); } }, touchStart:function(e){ this.startX=e.touches[0].clientX/game.documentZoom; this.startY=e.touches[0].clientY/game.documentZoom; _status.dragged=false; }, dialogtouchStart:function(e){ ui.click.touchStart.call(this,e); _status.dialogtouched=true; }, touchScroll:function(e) { if(_status.mousedragging) return; if(_status.draggingtouchdialog) return; if(!_status.dragged){ if (Math.abs(e.touches[0].clientX/game.documentZoom - this.startX) > 10 || Math.abs(e.touches[0].clientY/game.documentZoom - this.startY) > 10) { _status.dragged=true; } } if((this==ui.handcards1Container||this==ui.handcards2Container)&&!this.classList.contains('scrollh')){ e.preventDefault(); } else if(lib.device=='ios'&&this.scrollHeight<=this.offsetHeight+5&&this.scrollWidth<=this.offsetWidth+5){ e.preventDefault(); } else{ delete _status._swipeorigin; e.stopPropagation(); } }, autoskill:function(bool,node){ var list=lib.config.autoskilllist; if(bool){ list.remove(node.link); } else{ list.add(node.link); } game.saveConfig('autoskilllist',list); }, skillbutton:function(){ this.func(this.link); }, autoskill2:function(e){ this.classList.toggle('on'); var list=[]; if(lib.skill[this.link].frequent){ list.push(this.link); } if(lib.skill[this.link].subfrequent){ for(var i=0;i