"use strict"; const nonameInitialized=localStorage.getItem('noname_inited'); const assetURL=typeof nonameInitialized!='string'||nonameInitialized=='nodejs'?'':nonameInitialized; new Promise(resolve=>{ if('__core-js_shared__' in window) resolve(); else{ const coreJSBundle=document.createElement('script'); coreJSBundle.onerror=coreJSBundle.onload=resolve; coreJSBundle.src=`${assetURL}game/core-js-bundle.js`; document.head.appendChild(coreJSBundle); } }).then(()=>{ /** * @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 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:assetURL, 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); } }], }, /** * **无名杀消息推送库** * * 通过`EventTarget`机制,实现消息推送和接收的解耦, * 从而使消息接收方无需依赖发布方,发布方也无需考虑接收方 * * > `lib.announce`不是`actor`模型,若不存在订阅者,则消息发送将无意义 * * @example * // 甲扩展(如《千幻聆音》)在角色皮肤切换后,调用: * lib.announce.publish("skinChange", { * player, * playerName: "zhangfei", * originSkin: "image/xxx.jpg", * currentSkin: "image/yyy.jpg" * }); * * // 乙扩展监听此`skinChange`事件,并修改自己扩展相关界面的图片: * const method = lib.announce.subscribe("skinChange", (e) => { * div.setBackgroundImage(e.currentSkin); * }); * * // 若此时乙扩展不想继续订阅`skinChange`事件,可以通过`unsubscribe`解除订阅 * lib.announce.unsubscribe("skinChange", method); */ announce:new class{ constructor(){ /** * @type {HTMLElement} */ this._announce=document.createElement("Announce"); /** * @type {Map} */ this._announce_cache=new Map(); } /** * 推送任意数据给所有监听了指定事件的订阅者,并返回给定的数据 * * 若不存在订阅指定事件的订阅者,则推送的数据将无意义 * * @template T * @param {string} name - 要推送事件的名称 * @param {T} values - 要推送的数据 * @returns {T} */ publish(name,values){ if(this._announce) this._announce.dispatchEvent(new CustomEvent(name,{ detail:values })); return values; } /** * 订阅给定名字的事件,并返回给定的函数 * * 在事件触发时执行给定的函数 * * 给定的函数将被存储至当前实例中,用于取消订阅时获取 * * @template T * @param {string} name - 要订阅事件的名称 * @param {(values: T) => void} method - 事件触发时执行的函数 * @returns {(values: T) => void} */ subscribe(name,method){ if(this._announce&&this._announce_cache) { let subscribeFunction; if(this._announce_cache.has(method)){ let records=this._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]); this._announce_cache.set(method,records); } this._announce.addEventListener(name,subscribeFunction); } return method; } /** * 取消指定事件某一函数的订阅,并返回该函数 * * 给定的函数将不再于事件触发时执行,其余同事件需触发的函数不受限制 * * @template T * @param {string} name - 要取消订阅事件的名称 * @param {(values: T) => void} method - 订阅指定事件的函数 * @returns {(values: T) => void} */ unsubscribe(name,method){ if(this._announce&&this._announce_cache&&this._announce_cache.has(method)){ let records=this._announce_cache.get(method); const listener=records.get("Listener"); let eventTargets=records.get("EventTargets"); eventTargets.remove(name); if(eventTargets.length<=0) this._announce_cache.remove(method); this._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,option)=>{ if(event.step!=0||option.state!='end') 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,option)=>{ if(event.step!=0||option.state!='end') 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,option)=>{ if(event.step!=0||option.state!='end') 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,option)=>{ if(event.step!=0||option.state!='end') return; game.log(event.player,'触发了强化效果'); game.log(event.card,'造成的伤害+1'); event.increase('baseDamage',1); }], ['tao',(event,option)=>{ if(event.step!=0||option.state!='end') 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':'十', }, }, enable_commoner:{ name:'启用平民', init:false, restart:true, frequent:false, intro:'开启后游戏中将有一个平民(身份)加入游戏。
    具体规则请查看帮助。', }, choice_commoner:{ name:'平民候选武将数', init:'4', restart:true, item:{ '3':'三', '4':'四', '5':'五', '6':'六', '8':'八', '10':'十', }, }, enable_year_limit:{ name:'启用年机制', init:false, restart:true, frequent:false, intro:'开启后将会加入年机制。
    年机制的具体规则请查看帮助。', }, } }, 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, }, connect_aozhan:{ name:'鏖战模式', init:true, intro:'若开启此选项,则将在游戏中引入“鏖战模式”的规则:
    当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。
    ◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。
    注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。', 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_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, }, aozhan:{ name:'鏖战模式', init:true, frequent:true, restart:true, intro:'若开启此选项,则将在游戏中引入“鏖战模式”的规则:
    当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。
    ◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。
    注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。', }, separatism:{ name:'群雄割据', init:false, frequent:true, restart:true, intro:'开放不同势力组合,以优先亮出的武将牌作为自己的势力,双势力武将则使用列表的第一个势力' }, initshow_draw:{ name:'首亮奖励', item:{ 'off':'关闭', 'draw':'摸牌', 'mark':'标记', }, init:'mark', frequent: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协议来连接到联机服务器。
    请不要轻易勾选此项!', }, read_clipboard:{ name:'读取邀请链接', init:false, frequent:true, intro:'读取剪贴板以解析邀请链接自动加入联机房间', } } }, 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:{ /** * 部分函数的Promise版本 */ promises:{ /** * Promise版的`lib.init.js` * * @param {string} path - 文件路径 * @param {string | string[]} [file] - 文件名或文件名组,忽略则直接读取`path`的内容 * @returns {Promise} */ js:(path,file)=>new Promise((resolve,reject)=>lib.init.js(path,file,resolve,reject)), /** * Promise版的`lib.init.css` * * @param {string} path - 文件路径 * @param {string | string[]} [file] - 文件名或文件名组,忽略则直接读取`path`的内容 * @param {Element} [before] 新样式dom的位置 * @returns {Promise} */ css:(path,file,before)=>new Promise((resolve,reject)=>{ const style=lib.init.css(path,file,before); style.addEventListener("load",()=>resolve(style)); style.addEventListener("error",reject); }), /** * Promise版的`lib.init.req` * * @param {string} str - 要读取的地址 * @param {string} [master] * @returns {Promise} */ req:(str,master)=>new Promise((resolve,reject)=>lib.init.req(str,resolve,reject,master)), /** * Promise版的`lib.init.json` * * @param {string} url - 要读取的地址 * @returns {Promise} */ json:(url)=>new Promise((resolve,reject)=>lib.init.json(url,resolve,reject)), /** * Promise版的`lib.init.sheet` * * @returns {Promise} */ sheet(){ return new Promise((resolve,reject)=>{ const style=lib.init.sheet.apply(lib.init,arguments); style.addEventListener("load",()=>resolve(style)); style.addEventListener("error",reject); }) } }, init:function(){ if(typeof __dirname==='string'&&__dirname.length){ var dirsplit=__dirname.split('/'); for(var i=0;i{ const image=new Image(); image.src=`${lib.assetURL}${src}`; image.onerror=reject; }).catch(()=>new Promise((_,reject)=>{ const nameinfo=get.character(name); if(!nameinfo) reject('noinfo'); const sex=nameinfo[0]; src=`image/character/default_silhouette_${sex}${ext}`; const image=new Image(); image.src=`${lib.assetURL}${src}`; image.onload=()=>this.setBackgroundImage(src); image.onerror=()=>reject(`sex:${sex}`); })).catch(reason=>{ let sex; if(reason=='noinfo') sex='male'; else sex=reason.slice(4); src=`image/character/default_silhouette_${sex=='female'?'female':'male'}${ext}`; const image=new Image(); image.src=`${lib.assetURL}${src}`; image.onload=()=>this.setBackgroundImage(src); }); } return this; } }); HTMLDivElement.prototype.setBackgroundDB=function(img){ return game.getDB('image',img).then(src=>{ 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]; } }); 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; // 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.jsSync(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'); } }, /** * * @param {*} item * @param {Function} [scope] 作用域 * @returns */ parsex:function(item,scope){ //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; } if(!scope){ 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)); }else{ return scope(`function${hasDebugger?'*':''} anonymous(event,step,source,player,target,targets, card,cards,skill,forced,num,trigger,result, _status,lib,game,ui,get,ai){${str}}; anonymous;`); } } 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) return event.finish(); var currentResult=res.value; // TODO: use `event.debugger` to replace source if(typeof currentResult=="function") yield currentResult; else{ if(Array.isArray(currentResult)){ event.step=currentResult[1]; currentResult=currentResult[0]; } lastEvent=currentResult; } } }else if(item._parsed) return item; // falls through 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(Object.prototype.hasOwnProperty.call(func, 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