"use strict";
{
	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 ua=navigator.userAgent.toLowerCase();
			const ios=ua.includes('iphone')||ua.includes('ipad')||ua.includes('macintosh');
			//electron
			if(typeof window.process=='object'&&typeof window.require=='function'){
				const versions=window.process.versions;
				const electronVersion=parseFloat(versions.electron);
				let remote;
				if(electronVersion>=14){
					remote=require('@electron/remote');
				}else{
					remote=require('electron').remote;
				}
				const thisWindow=remote.getCurrentWindow();
				thisWindow.destroy();
				window.process.exit();
			}
			//android-cordova环境
			//ios-cordova环境或ios浏览器环境
			//非ios的网页版
			else if(!ios){
				window.close();
			}
		}
	}
	const nonameInitialized=localStorage.getItem('noname_inited');
	const GeneratorFunction=(function*(){}).constructor;
	// gnc: GeNCoroutine
	const gnc={
		of:fn=>gnc.is.generatorFunc(fn)?function genCoroutine(){
			let gen=fn.apply(this,arguments);
			gen.status="next";
			gen.state=undefined;
			const callback=(resolve,reject)=>{
				let result,
					nexts=resolve,
					throws=reject;
				try{
					result=gen[gen.status](gen.state);
				}catch(error){
					reject(error);
					return;
				}
				if(!result.done){
					nexts=(item)=>{
						gen.state=item;
						gen.status="next";
						callback(resolve,reject);
					}
					throws=(err)=>{
						gen.state=err;
						gen.status="throw";
						callback(resolve,reject);
					}
				}
				result=result.value;
				Promise.resolve(result).then(nexts,throws);
			}
			return new Promise(callback);
		}:(()=>{throw new TypeError("gnc.of needs a GeneratorFunction.")})(),
		is:{
			coroutine:item=>typeof item=="function"&&item.name=="genCoroutine",
			generatorFunc:item=>item instanceof GeneratorFunction,
			generator:item=>(typeof item=="object")&&("constructor" in item)&&item.constructor&&("constructor" in item.constructor)&&item.constructor.constructor===GeneratorFunction
		}
	};
	const _status={
		paused:false,
		paused2:false,
		paused3:false,
		over:false,
		clicked:false,
		auto:false,
		event:{
			finished:true,
			next:[],
			after:[]
		},
		ai:{},
		lastdragchange:[],
		skillaudio:[],
		dieClose:[],
		dragline:[],
		dying:[],
		globalHistory:[{
			cardMove:[],
			custom:[],
			useCard:[],
			changeHp:[],
			everything:[],
		}],
		cardtag:{
			yingbian_zhuzhan:[],
			yingbian_kongchao:[],
			yingbian_fujia:[],
			yingbian_canqu:[],
			yingbian_force:[]
		},
		renku:[],
		prehidden_skills:[],
		postReconnect:{},
	};
	const lib={
		configprefix:'noname_0.9_',
		versionOL:27,
		updateURLS:{
			coding:'https://raw.fgit.cf/libccy/noname',
			github:'https://raw.githubusercontent.com/libccy/noname',
		},
		updateURL:'https://raw.githubusercontent.com/libccy/noname',
		mirrorURL:'https://raw.fgit.cf/libccy/noname',
		hallURL:'47.99.105.222',
		assetURL:typeof nonameInitialized!='string'||nonameInitialized=='nodejs'?'':nonameInitialized,
		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);

				let color1,color2;
				if (typeof config.color=="string"&&/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(config.color)){
					let c1=parseInt(`0x${item[1].slice(1, 3)}`);
					let c2=parseInt(`0x${item[1].slice(3, 5)}`);
					let c3=parseInt(`0x${item[1].slice(5, 7)}`);
					color1=color2=[c1,c2,c3,1];
				}
				else if(Array.isArray(config.color)&&config.color.length>=2&&config.color.length<=4){
					if(config.color.every(item=>Array.isArray(item))){
						color1=config.color[0];
						color2=config.color[1];
					}
					else{
						let color=config.color.slice();
						if(color.length==3) color.push(1);
						color1=color2=color;
					}
				}
				if(color1&&color2){
					const cs=lib.linq.cselector;
					const g1=cs.group(
						cs.of(
							cs.class("card","fullskin",`${nature}`),
							'>',
							cs.class("name")
						)
					);
					let result={};
					result[g1]={
						color:`rgba(${color1.join()})`,
						border:cs.merge(
							'1px',
							'solid',
							`rgba(${color2.join()})`
						),
					};
					game.dynamicStyle.addObject(result);

					const g2=cs.group(
						cs.of(
							cs.class("tempname",`${nature}`),
							':not([data-nature])>',
							cs.class("span")
						)
					)
					let result2={};
					result2[g2]={
						color:`rgba(${color1.join()})`,
					};
					game.dynamicStyle.addObject(result2);
				}
			}],
		},
		announce:{
			init(){
				_status._announce=document.createElement("Announce");
				_status._announce_cache=new Map();
				delete lib.announce.init;
			},
			//推送一个对象给所有监听了name的订阅者。
			publish(name,values){
				if(_status._announce) _status._announce.dispatchEvent(new CustomEvent(name,{
					detail:values
				}));
				return values;
			},
			//订阅name相关的事件。
			subscribe(name,method){
				if(_status._announce&&_status._announce_cache) {
					let subscribeFunction;
					if(_status._announce_cache.has(method)){
						let records=_status._announce_cache.get(method);
						subscribeFunction=records.get("Listener");
						records.get("EventTargets").add(name);
					}
					else{
						subscribeFunction=event=>method(event.detail);
						let records=new Map();
						records.set("Listener",subscribeFunction);
						records.set("EventTargets",[name]);
						_status._announce_cache.set(method,records);
					}
					_status._announce.addEventListener(name,subscribeFunction);
				}
				return method;
			},
			//取消对事件name的订阅
			unsubscribe(name,method){
				if(_status._announce&&_status._announce_cache&&_status._announce_cache.has(method)){
					let records=_status._announce_cache.get(method);
					const listener=records.get("Listener");
					let eventTargets=records.get("EventTargets");
					eventTargets.remove(name);
					if(eventTargets.length<=0) _status._announce_cache.remove(method);
					_status._announce.removeEventListener(name,listener);
				}
				return method;
			}
		},
		objectURL:new Map(),
		hookmap:{},
		imported:{},
		layoutfixed:['chess','tafang','stone'],
		pinyins:{
			_metadata:{
				shengmu:['zh','ch','sh','b','p','m','f','d','t','l','n','g','k','h','j','q','x','r','z','c','s','y','w'],
				special_shengmu:['j','q','x','y'],
				feijiemu:{
					i:['ing','iu','ie','in'],
					u:['ui','un'],
					ü:['üe','ün'],
				},
				zhengtirendu:['zhi','chi','shi','ri','zi','ci','si'],
				yunjiao:{
					'一麻':['a','ia','ua'],
					'二波':['o','e','uo'],
					'三皆':['ie','üe'],
					'四开':['ai','uai'],
					'五微':['ei','ui'],
					'六豪':['ao','iao'],
					'七尤':['ou','iu'],
					'八寒':['an','ian','uan','üan'],
					'九文':['en','in','un','ün'],
					'十唐':['ang','iang','uang'],
					'十一庚':['eng','ing','ong','ung'],
					'十二齐':['i','er','ü'],
					'十三支':['-i'],
					'十四姑':['u'],
				},
			}
		},
		//Yingbian
		//应变
		yingbian:{
			condition:{
				color:new Map([
					['zhuzhan','wood'],
					['kongchao','soil'],
					['fujia','orange'],
					['canqu','fire'],
					['force','metal']
				]),
				complex:new Map([
					['zhuzhan',function(event){
						const yingbianZhuzhan=game.createEvent('yingbianZhuzhan');
						yingbianZhuzhan.player=event.player;
						yingbianZhuzhan.card=event.card;
						yingbianZhuzhan._trigger=event;
						yingbianZhuzhan.yingbianZhuzhanAI=event.yingbianZhuzhanAI;
						yingbianZhuzhan.afterYingbianZhuzhan=event.afterYingbianZhuzhan;
						yingbianZhuzhan.setContent(()=>{
							'step 0'
							event._global_waiting=true;
							event.send=(player,card,source,targets,id,id2,yingbianZhuzhanAI,skillState)=>{
								if(skillState) player.applySkills(skillState);
								var type=get.type2(card),str=get.translation(source);
								if(targets&&targets.length) str+=`对${get.translation(targets)}`;
								str+=`使用了${get.translation(card)},是否弃置一张${get.translation(type)}为其助战?`;
								player.chooseCard({
									filterCard:(card,player)=>get.type2(card)==type&&lib.filter.cardDiscardable(card,player),
									prompt:str,
									position:'h',
									_global_waiting:true,
									id:id,
									id2:id2,
									ai:typeof yingbianZhuzhanAI=='function'?yingbianZhuzhanAI(player,card,source,targets):cardx=>{
										var info=get.info(card);
										if(info&&info.ai&&info.ai.yingbian){
											var ai=info.ai.yingbian(card,source,targets,player);
											if(!ai) return 0;
											return ai-get.value(cardx);
										}
										else if(get.attitude(player,source)<=0) return 0;
										return 5-get.value(cardx);
									}
								});
								if(!game.online) return;
								_status.event._resultid=id;
								game.resume();
							};
							'step 1'
							var type=get.type2(card);
							event.list=game.filterPlayer(current=>current!=player&&current.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<list.length;i++){
								var current=list[i];
								if(current.isOnline()){
									withol=true;
									current.wait(sendback);
									current.send(event.send,current,event.card,player,trigger.targets,event.id,trigger.parent.id,trigger.yingbianZhuzhanAI,get.skillState(current));
									list.splice(i--,1);
								}
								else if(current==game.me){
									withme=true;
									event.send(current,event.card,player,trigger.targets,event.id,trigger.parent.id,trigger.yingbianZhuzhanAI);
									list.splice(i--,1);
								}
							}
							if(!withme) event.goto(6);
							if(_status.connectMode&&(withme||withol)) game.players.forEach(value=>{
								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','无视条件执行所有选项']
			])
		},
		//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:{
					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:'防止屏幕自动关闭<br>注:旧版本通过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<nodeyy.childElementCount;i++){
												if(nodeyy.childNodes[i]._link==str){
													nodeyy.childNodes[i].remove();
													break;
												}
											}
											var textMenu=ui.create.div('',str,nodeyy,function(){
												var node=this.parentNode._link;
												var config=node._link.config;
												node._link.current=this.link;
												var tmpName=node.lastChild.innerHTML;
												node.lastChild.innerHTML=config.item[this._link];
												if(config.onclick){
													if(config.onclick.call(node,this._link,this)===false){
														node.lastChild.innerHTML=tmpName;
													}
												}
												if(config.update){
													config.update();
												}
											});
											textMenu._link=str;
											nodezz.item[name]=str;
											alert('已添加扩展地址:'+str);
										}
									})
								}
							});
						},
					},
					extension_delete:{
						name:'删除当前扩展地址',
						clear:true,
						unfrequent:true,
						onclick:function(){
							var bool=false,map=lib.config.extension_sources;
							for(var i in map){
								if(i!=lib.config.extension_source){
									bool=true;
									break;
								}
							}
							if(!bool){
								alert('不能删除最后一个扩展地址!');
								return;
							}
							var name=lib.config.extension_source;
							game.saveConfig('extension_source',i);
							delete map[name];
							game.saveConfig('extension_sources',map);
							var nodexx=ui.extension_source;
							nodexx.updateInner();
							var nodeyy=nodexx._link.menu;
							var nodezz=nodexx._link.config;
							for(var i=0;i<nodeyy.childElementCount;i++){
								if(nodeyy.childNodes[i]._link==name){
									nodeyy.childNodes[i].remove();
									break;
								}
							}
							delete nodezz.item[name];
							alert('已删除扩展地址:'+name);
						},
					},
					update:function(config,map){
						if('ontouchstart' in document){
							map.touchscreen.show();
						}
						else{
							map.touchscreen.hide();
						}
						if(lib.device||lib.node){
							map.auto_check_update.show();
						}
						else{
							map.auto_check_update.hide();
						}
						if(lib.device){
							map.enable_vibrate.show();
							map.keep_awake.show();
						}
						else{
							map.enable_vibrate.hide();
							map.keep_awake.hide();
						}
						// if(config.enable_pressure){
						// 	map.pressure_click.show();
						// 	if(lib.device){
						// 		map.pressure_taptic.show();
						// 	}
						// 	else{
						// 		map.pressure_taptic.hide();
						// 	}
						// }
						// else{
						// 	map.pressure_click.hide();
						// 	map.pressure_taptic.hide();
						// }
						if(lib.config.touchscreen){
							map.mousewheel.hide();
							map.hover_all.hide();
							map.hover_handcard.hide();
							map.hoveration.hide();
							map.right_info.hide();
							map.right_click.hide();
							map.longpress_info.show();
							map.swipe.show();
							if(lib.config.swipe){
								map.swipe_up.show();
								map.swipe_down.show();
								map.swipe_left.show();
								map.swipe_right.show();
							}
							else{
								map.swipe_up.hide();
								map.swipe_down.hide();
								map.swipe_left.hide();
								map.swipe_right.hide();
							}
						}
						else{
							map.mousewheel.show();
							map.hover_all.show();
							map.right_info.show();
							map.right_click.show();
							map.longpress_info.hide();
							if(!config.hover_all){
								map.hover_handcard.hide();
								map.hoveration.hide();
							}
							else{
								map.hover_handcard.show();
								map.hoveration.show();
							}
							map.swipe.hide();
							map.swipe_up.hide();
							map.swipe_down.hide();
							map.swipe_left.hide();
							map.swipe_right.hide();
						}
						if(lib.config.enable_drag){
							if(lib.config.touchscreen){
								map.enable_dragline.hide();
								map.enable_touchdragline.show();
							}
							else{
								map.enable_dragline.show();
								map.enable_touchdragline.hide();
							}
						}
						else{
							map.enable_dragline.hide();
							map.enable_touchdragline.hide();
						}
						if(!get.is.phoneLayout()){
							map.round_menu_func.hide();
						}
						else{
							map.round_menu_func.show();
						}
						if(!lib.node&&lib.device!='ios'){
							map.confirm_exit.show();
						}
						else{
							map.confirm_exit.hide();
						}
						if(config.dev){
							map.errstop.show();
						}
						else{
							map.errstop.hide();
						}
					}
				}
			},
			appearence:{
				name:'外观',
				config:{
					theme:{
						name:'主题',
						init:'woodden',
						item:{},
						visualMenu:function(node,link){
							if(!node.menu){
								node.className='button character themebutton '+link;
								node.menu=ui.create.div(node,'','<div></div><div></div><div></div><div></div>');
							}
						},
						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;i<page.childElementCount;i++){
									if(page.childNodes[i].classList.contains('button')){
										var link=page.childNodes[i]._link;
										if(link&&link!='default'){
											var str;
											if(this.classList.contains('active')){
												if(link.startsWith('custom_')||link.startsWith('cdv_')){
													str='删除';
												}
												else{
													str='隐藏';
												}
											}
											else{
												str=item[link];
											}
											page.childNodes[i].firstChild.innerHTML=get.verticalStr(str);
										}
									}
								}
							};
							ui.create.div('.menubutton','编辑背景',node,editbg);
						},
						visualMenu:function(node,link,name,config){
							node.className='button character';
							node.style.backgroundImage='';
							node.style.backgroundSize='';
							if(node.firstChild){
								node.firstChild.innerHTML=get.verticalStr(name);
							}
							if(link=='default'||link.startsWith('custom_')){
								node.style.backgroundImage='none';
								node.classList.add('dashedmenubutton');
								if(link.startsWith('custom_')){
									game.getDB('image',link,function(fileToLoad){
										if(!fileToLoad) return;
										var fileReader = new FileReader();
										fileReader.onload = function(fileLoadedEvent)
										{
											var data = fileLoadedEvent.target.result;
											node.style.backgroundImage='url('+data+')';
											node.style.backgroundSize='cover';
											node.classList.remove('dashedmenubutton');
										};
										fileReader.readAsDataURL(fileToLoad, "UTF-8");
									});
								}
								else{
									node.parentNode.defaultNode=node;
								}
							}
							else{
								node.setBackgroundImage('image/background/'+link+'.jpg');
								node.style.backgroundSize='cover';
							}
						},
						onclick:function(background,node){
							if(node&&node.firstChild){
								var menu=node.parentNode;
								if(node.firstChild.innerHTML==get.verticalStr('隐藏')){
									menu.parentNode.noclose=true;
									node.remove();
									menu.updateBr();
									if(!lib.config.prompt_hidebg){
										alert('隐藏的背景可通过选项-其它-重置隐藏内容恢复');
										game.saveConfig('prompt_hidebg',true);
									}
									lib.config.hiddenBackgroundPack.add(background);
									game.saveConfig('hiddenBackgroundPack',lib.config.hiddenBackgroundPack);
									delete lib.configMenu.appearence.config.image_background.item[background];
									if(lib.config.image_background==background){
										background='default';
										this.lastChild.innerHTML='默认';
									}
									else{
										this.lastChild.innerHTML=lib.configMenu.appearence.config.image_background.item[lib.config.image_background];
										return;
									}
								}
								else if(node.firstChild.innerHTML==get.verticalStr('删除')){
									menu.parentNode.noclose=true;
									if(confirm('是否删除此背景?(此操作不可撤销)')){
										node.remove();
										menu.updateBr();
										lib.config.customBackgroundPack.remove(background);
										game.saveConfig('customBackgroundPack',lib.config.customBackgroundPack);
										if(background.startsWith('cdv_')){
											game.removeFile('image/background/'+background+'.jpg');
										}
										else{
											game.deleteDB('image',background);
										}
										delete lib.configMenu.appearence.config.image_background.item[background];
										if(lib.config.image_background==background){
											background='default';
											this.lastChild.innerHTML='默认';
										}
										else{
											this.lastChild.innerHTML=lib.configMenu.appearence.config.image_background.item[lib.config.image_background];
											return;
										}
									}
								}
							}
							game.saveConfig('image_background',background);
							lib.init.background();
							game.updateBackground();
						},
					},
					image_background_random:{
						name:'随机背景',
						init:false,
						onclick:function(bool){
							game.saveConfig('image_background_random',bool);
							lib.init.background();
						}
					},
					image_background_blur:{
						name:'背景模糊',
						init:false,
						onclick:function(bool){
							game.saveConfig('image_background_blur',bool);
							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)';
							}
							else{
								ui.background.style.filter='';
								ui.background.style.webkitFilter='';
								ui.background.style.transform='';
							}
						},
					},
					phonelayout:{
						name:'触屏布局',
						init:false,
						onclick:function(bool){
							if(get.is.nomenu('phonelayout',bool)) return false;
							game.saveConfig('phonelayout',bool);
							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');
							}
						}
					},
					change_skin:{
						name:'开启换肤',
						init:true,
						intro:'在武将的右键菜单中换肤,皮肤可在选项-文件-图片文件-皮肤图片中添加'
					},
					change_skin_auto:{
						name:'自动换肤',
						init:'off',
						item:{
							'off':'关闭',
							'30000':'半分钟',
							'60000':'一分钟',
							'120000':'两分钟',
							'300000':'五分钟',
						},
						intro:'游戏每进行一段时间自动为一个随机角色更换皮肤',
						onclick:function(item){
							game.saveConfig('change_skin_auto',item);
							clearTimeout(_status.skintimeout);
							if(item!='off'){
								_status.skintimeout=setTimeout(ui.click.autoskin,parseInt(item));
							}
						}
					},
					card_style:{
						name:'卡牌样式',
						init:'default',
						intro:'设置正面朝上的卡牌的样式',
						item:{
							wood:'木纹',
							music:'音乐',
							simple:'原版',
							ol:'手杀',
							// new:'新版',
							custom:'自定',
							default:'默认',
						},
						visualBar:function(node,item,create,switcher){
							if(node.created){
								return;
							}
							var button;
							for(var i=0;i<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton','添加图片',node,function(file){
								if(file){
									game.putDB('image','card_style',file,function(){
										game.getDB('image','card_style',function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.style.backgroundImage='url('+data+')';
												button.className='button card fullskin';
												node.classList.add('showdelete');
											};
											fileReader.readAsDataURL(fileToLoad, "UTF-8");
										});
									});
								}
							}).inputNode.accept='image*';
							deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){
								if(confirm('确定删除自定义图片?(此操作不可撤销)')){
									game.deleteDB('image','card_style');
									button.style.backgroundImage='none';
									button.className='button character dashedmenubutton';
									node.classList.remove('showdelete');
									if(lib.config.card_style=='custom'){
										lib.configMenu.appearence.config.card_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.className='button card fullskin';
							node.style.backgroundSize='100% 100%';
							switch(link){
								case 'default':case 'custom':{
									if(lib.config.theme=='simple'){
										node.style.backgroundImage='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))';
										node.className='button character';
									}
									else{
										node.style.backgroundImage='none';
										node.className='button character dashedmenubutton';
									}
									break;
								}
								case 'new':node.setBackgroundImage('theme/style/card/image/new.png');break;
								case 'ol':node.setBackgroundImage('theme/style/card/image/ol.png');break;
								case 'wood':node.setBackgroundImage('theme/woodden/wood.jpg');node.style.backgroundSize='initial';break;
								case 'music':node.setBackgroundImage('theme/music/wood3.png');break;
								case 'simple':node.setBackgroundImage('theme/simple/card.png');break;
							}
							if(link=='custom'){
								node.classList.add('transparent');
								game.getDB('image','card_style',function(fileToLoad){
									if(!fileToLoad) return;
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										node.style.backgroundImage='url('+data+')';
										node.className='button card fullskin';
										node.parentNode.lastChild.classList.add('showdelete');
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						onclick:function(layout){
							game.saveConfig('card_style',layout);
							var style=ui.css.card_style;
							ui.css.card_style=lib.init.css(lib.assetURL+'theme/style/card',lib.config.card_style);
							style.remove();
							if(ui.css.card_stylesheet){
								ui.css.card_stylesheet.remove();
								delete ui.css.card_stylesheet;
							}
							if(layout=='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");
								});
							}
						},
						unfrequent:true,
					},
					cardback_style:{
						name:'卡背样式',
						intro:'设置背面朝上的卡牌的样式',
						init:'default',
						item:{
							// wood:'木纹',
							// music:'音乐',
							official:'原版',
							// new:'新版',
							feicheng:'废城',
							liusha:'流沙',
							ol:'手杀',
							custom:'自定',
							default:'默认',
						},
						visualBar:function(node,item,create,switcher){
							if(node.created){
								return;
							}
							var button;
							for(var i=0;i<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton','添加图片',node,function(file){
								if(file){
									game.putDB('image','cardback_style',file,function(){
										game.getDB('image','cardback_style',function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.style.backgroundImage='url('+data+')';
												button.className='button character';
												node.classList.add('showdelete');
											};
											fileReader.readAsDataURL(fileToLoad, "UTF-8");
										});
									});
								}
							}).inputNode.accept='image/*';
							ui.create.filediv('.menubutton.deletebutton.addbutton','添加翻转图片',node,function(file){
								if(file){
									game.putDB('image','cardback_style2',file,function(){
										node.classList.add('hideadd');
									});
								}
							}).inputNode.accept='image/*';
							deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){
								if(confirm('确定删除自定义图片?(此操作不可撤销)')){
									game.deleteDB('image','cardback_style');
									game.deleteDB('image','cardback_style2');
									button.style.backgroundImage='none';
									button.className='button character dashedmenubutton';
									node.classList.remove('showdelete');
									node.classList.remove('hideadd');
									if(lib.config.cardback_style=='custom'){
										lib.configMenu.appearence.config.cardback_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.style.backgroundSize='100% 100%';
							switch(link){
								case 'default':case 'custom':{
									node.style.backgroundImage='none';
									node.className='button character dashedmenubutton';
									break;
								}
								case 'new':node.className='button character';node.setBackgroundImage('theme/style/cardback/image/new.png');break;
								case 'feicheng':node.className='button character';node.setBackgroundImage('theme/style/cardback/image/feicheng.png');break;
								case 'official':node.className='button character';node.setBackgroundImage('theme/style/cardback/image/official.png');break;
								case 'liusha':node.className='button character';node.setBackgroundImage('theme/style/cardback/image/liusha.png');break;
								case 'ol':node.className='button character';node.setBackgroundImage('theme/style/cardback/image/ol.png');break;
								case 'wood':node.className='button card fullskin';node.setBackgroundImage('theme/woodden/wood.jpg');node.style.backgroundSize='initial';break;
								case 'music':node.className='button card fullskin';node.setBackgroundImage('theme/music/wood3.png');break;
							}
							if(link=='custom'){
								node.classList.add('transparent');
								game.getDB('image','cardback_style',function(fileToLoad){
									if(!fileToLoad) return;
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										node.style.backgroundImage='url('+data+')';
										node.className='button character';
										node.parentNode.lastChild.classList.add('showdelete');
										game.getDB('image','cardback_style2',function(file){
											if(file){
												node.parentNode.lastChild.classList.add('hideadd');
											}
										});
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						onclick:function(layout){
							game.saveConfig('cardback_style',layout);
							var style=ui.css.cardback_style;
							ui.css.cardback_style=lib.init.css(lib.assetURL+'theme/style/cardback',lib.config.cardback_style);
							style.remove();
							if(ui.css.cardback_stylesheet){
								ui.css.cardback_stylesheet.remove();
								delete ui.css.cardback_stylesheet;
							}
							if(ui.css.cardback_stylesheet2){
								ui.css.cardback_stylesheet2.remove();
								delete ui.css.cardback_stylesheet2;
							}
							if(layout=='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+')}');
										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");
										});
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						unfrequent:true,
					},
					hp_style:{
						name:'体力条样式',
						init:'ol',
						item:{
							default:'默认',
							// official:'勾玉',
							emotion:'表情',
							glass:'勾玉',
							round:'国战',
							ol:'手杀',
							xinglass:'双鱼',
							xinround:'OL',
							custom:'自定',
						},
						visualBar:function(node,item,create,switcher){
							if(node.created){
								return;
							}
							var button;
							for(var i=0;i<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton.addbutton','添加图片',node,function(file){
								if(file&&node.currentDB){
									game.putDB('image','hp_style'+node.currentDB,file,function(){
										game.getDB('image','hp_style'+node.currentDB,function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.childNodes[node.currentDB-1].style.backgroundImage='url('+data+')';
												button.classList.add('shown');
												node.classList.add('showdelete');
												node.currentDB++;
												if(node.currentDB>4){
													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;i<button.childElementCount;i++){
										button.childNodes[i].style.backgroundImage='none';
									}
									node.classList.remove('showdelete');
									node.classList.remove('hideadd');
									if(lib.config.hp_style=='custom'){
										lib.configMenu.appearence.config.hp_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
									button.classList.remove('shown');
									node.currentDB=1;
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.className='button hpbutton dashedmenubutton';
							node.innerHTML='';
							for(var i=1;i<=4;i++){
								var div=ui.create.div(node);
								if(link=='default'){
									ui.create.div(div);
								}
								else if(link!='custom'){
									div.setBackgroundImage('theme/style/hp/image/'+link+i+'.png');
								}
								if(i==4){
									div.style.webkitFilter='grayscale(1)';
								}
							}
							if(link=='custom'){
								node.classList.add('transparent');
								var getDB=function(num){
									node.parentNode.lastChild.currentDB=num;
									game.getDB('image','hp_style'+num,function(fileToLoad){
										if(!fileToLoad) return;
										var fileReader = new FileReader();
										fileReader.onload = function(fileLoadedEvent)
										{
											var data = fileLoadedEvent.target.result;
											node.childNodes[num-1].style.backgroundImage='url('+data+')';
											node.classList.add('shown');
											node.parentNode.lastChild.classList.add('showdelete');
											if(num<4){
												getDB(num+1);
											}
											else{
												node.parentNode.lastChild.classList.add('hideadd');
												node.classList.remove('transparent');
												delete node.parentNode.firstChild.currentDB;
											}
										};
										fileReader.readAsDataURL(fileToLoad, "UTF-8");
									});
								}
								getDB(1);
							}
						},
						onclick:function(layout){
							game.saveConfig('hp_style',layout);
							var style=ui.css.hp_style;
							ui.css.hp_style=lib.init.css(lib.assetURL+'theme/style/hp',lib.config.hp_style);
							style.remove();
							if(ui.css.hp_stylesheet1){
								ui.css.hp_stylesheet1.remove();
								delete ui.css.hp_stylesheet1;
							}
							if(ui.css.hp_stylesheet2){
								ui.css.hp_stylesheet2.remove();
								delete ui.css.hp_stylesheet2;
							}
							if(ui.css.hp_stylesheet3){
								ui.css.hp_stylesheet3.remove();
								delete ui.css.hp_stylesheet3;
							}
							if(ui.css.hp_stylesheet4){
								ui.css.hp_stylesheet4.remove();
								delete ui.css.hp_stylesheet4;
							}
							if(layout=='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");
								});
							}
						},
						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<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton','添加图片',node,function(file){
								if(file){
									game.putDB('image','player_style',file,function(){
										game.getDB('image','player_style',function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.style.backgroundImage='url('+data+')';
												button.className='button character';
												button.style.backgroundSize='100% 100%';
												node.classList.add('showdelete');
											};
											fileReader.readAsDataURL(fileToLoad, "UTF-8");
										});
									});
								}
							}).inputNode.accept='image/*';
							deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){
								if(confirm('确定删除自定义图片?(此操作不可撤销)')){
									game.deleteDB('image','player_style');
									button.style.backgroundImage='none';
									button.className='button character dashedmenubutton';
									node.classList.remove('showdelete');
									if(lib.config.player_style=='custom'){
										lib.configMenu.appearence.config.player_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.className='button character';
							node.style.backgroundSize='';
							node.style.height='108px';
							switch(link){
								case 'default':case 'custom':{
									node.style.backgroundImage='none';
									node.className='button character dashedmenubutton';
									break;
								}
								case 'wood':node.setBackgroundImage('theme/woodden/wood.jpg');break;
								case 'music':node.style.backgroundImage='linear-gradient(#4b4b4b, #464646)';break;
								case 'simple':node.style.backgroundImage='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))';break;
							}
							if(link=='custom'){
								node.classList.add('transparent');
								game.getDB('image','player_style',function(fileToLoad){
									if(!fileToLoad) return;
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										node.style.backgroundImage='url('+data+')';
										node.className='button character';
										node.parentNode.lastChild.classList.add('showdelete');
										node.style.backgroundSize='100% 100%';
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						onclick:function(layout){
							game.saveConfig('player_style',layout);
							if(ui.css.player_stylesheet){
								ui.css.player_stylesheet.remove();
								delete ui.css.player_stylesheet;
							}
							if(layout=='custom'){
								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");
								});
							}
							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)';break;
									case 'simple':str='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))';break;
								}
								ui.css.player_stylesheet=lib.init.sheet('#window .player{background-image:'+str+'}');
							}
						},
						unfrequent:true,
					},
					border_style:{
						name:'角色边框',
						init:'default',
						intro:'设置角色边框的样式,当设为自动时,样式将随着一局游戏中伤害或击杀的数量自动改变',
						item:{
							gold:'金框',
							silver:'银框',
							bronze:'铜框',
							dragon_gold:'金龙',
							dragon_silver:'银龙',
							dragon_bronze:'玉龙',
							custom:'自定',
							auto:'自动',
							default:'默认',
						},
						visualBar:function(node,item,create,switcher){
							if(node.created){
								return;
							}
							var button;
							for(var i=0;i<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton','添加图片',node,function(file){
								if(file){
									game.putDB('image','border_style',file,function(){
										game.getDB('image','border_style',function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.style.backgroundImage='url('+data+')';
												button.className='button character';
												button.style.backgroundSize='100% 100%';
												node.classList.add('showdelete');
											};
											fileReader.readAsDataURL(fileToLoad, "UTF-8");
										});
									});
								}
							}).inputNode.accept='image/*';
							deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){
								if(confirm('确定删除自定义图片?(此操作不可撤销)')){
									game.deleteDB('image','border_style');
									button.style.backgroundImage='none';
									button.className='button character dashedmenubutton';
									node.classList.remove('showdelete');
									if(lib.config.border_style=='custom'){
										lib.configMenu.appearence.config.border_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.className='button character';
							node.style.backgroundSize='';
							node.style.height='108px';
							node.dataset.decoration='';
							if(link=='default'||link=='custom'||link=='auto'){
								node.style.backgroundImage='none';
								node.className='button character dashedmenubutton';
							}
							else{
								if(link.startsWith('dragon_')){
									link=link.slice(7);
									node.dataset.decoration=link;
								}
								node.setBackgroundImage('theme/style/player/'+link+'1.png');
								node.style.backgroundSize='100% 100%';
							}
							if(link=='custom'){
								node.classList.add('transparent');
								game.getDB('image','border_style',function(fileToLoad){
									if(!fileToLoad) return;
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										node.style.backgroundImage='url('+data+')';
										node.className='button character';
										node.parentNode.lastChild.classList.add('showdelete');
										node.style.backgroundSize='100% 100%';
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						onclick:function(layout){
							game.saveConfig('border_style',layout);
							if(ui.css.border_stylesheet){
								ui.css.border_stylesheet.remove();
								delete ui.css.border_stylesheet;
							}
							if(layout=='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.id="ui.css.border";
										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");
								});
							}
							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:'<strong>击杀</strong> 每击杀一人,边框提升两级<br><strong>伤害</strong> 每造成两点伤害,边框提升一级<br><strong>混合</strong> 击杀量决定边框颜色,伤害量决定边框装饰',
						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<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton','添加图片',node,function(file){
								if(file){
									game.putDB('image','menu_style',file,function(){
										game.getDB('image','menu_style',function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.style.backgroundImage='url('+data+')';
												button.style.backgroundSize='cover';
												button.className='button character';
												node.classList.add('showdelete');
											};
											fileReader.readAsDataURL(fileToLoad, "UTF-8");
										});
									});
								}
							}).inputNode.accept='image/*';
							deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){
								if(confirm('确定删除自定义图片?(此操作不可撤销)')){
									game.deleteDB('image','menu_style');
									button.style.backgroundImage='none';
									button.style.backgroundSize='auto';
									button.className='button character dashedmenubutton';
									node.classList.remove('showdelete');
									if(lib.config.menu_style=='custom'){
										lib.configMenu.appearence.config.menu_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.className='button character';
							node.style.backgroundSize='auto';
							switch(link){
								case 'default':case 'custom':{
									node.style.backgroundImage='none';
									node.classList.add('dashedmenubutton');
									break;
								}
								case 'wood':node.setBackgroundImage('theme/woodden/wood2.png');break;
								case 'music':node.style.backgroundImage='linear-gradient(#4b4b4b, #464646)';break;
								case 'simple':node.style.backgroundImage='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))';break;
							}
							if(link=='custom'){
								node.classList.add('transparent');
								game.getDB('image','menu_style',function(fileToLoad){
									if(!fileToLoad) return;
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										node.style.backgroundImage='url('+data+')';
										node.style.backgroundSize='cover';
										node.className='button character';
										node.parentNode.lastChild.classList.add('showdelete');
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						onclick:function(layout){
							game.saveConfig('menu_style',layout);
							if(ui.css.menu_stylesheet){
								ui.css.menu_stylesheet.remove();
								delete ui.css.menu_stylesheet;
							}
							if(layout=='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");
								});
							}
							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;i<node.parentNode.childElementCount;i++){
								if(node.parentNode.childNodes[i]._link=='custom'){
									button=node.parentNode.childNodes[i];
								}
							}
							if(!button){
								return;
							}
							node.created=true;
							var deletepic;
							ui.create.filediv('.menubutton','添加图片',node,function(file){
								if(file){
									game.putDB('image','control_style',file,function(){
										game.getDB('image','control_style',function(fileToLoad){
											if(!fileToLoad) return;
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												var data = fileLoadedEvent.target.result;
												button.style.backgroundImage='url('+data+')';
												button.className='button character controlbutton';
												node.classList.add('showdelete');
											};
											fileReader.readAsDataURL(fileToLoad, "UTF-8");
										});
									});
								}
							}).inputNode.accept='image/*';
							deletepic=ui.create.div('.menubutton.deletebutton','删除图片',node,function(){
								if(confirm('确定删除自定义图片?(此操作不可撤销)')){
									game.deleteDB('image','control_style');
									button.style.backgroundImage='none';
									button.className='button character controlbutton dashedmenubutton';
									node.classList.remove('showdelete');
									if(lib.config.control_style=='custom'){
										lib.configMenu.appearence.config.control_style.onclick('default');
										switcher.lastChild.innerHTML='默认';
									}
									button.classList.add('transparent');
								}
							});
						},
						visualMenu:function(node,link,name,config){
							node.className='button character controlbutton';
							node.style.backgroundSize='';
							switch(link){
								case 'default':case 'custom':{
									node.style.backgroundImage='none';
									node.classList.add('dashedmenubutton');
									break;
								}
								case 'wood':node.setBackgroundImage('theme/woodden/wood.jpg');break;
								case 'music':node.style.backgroundImage='linear-gradient(#4b4b4b, #464646)';break;
								case 'simple':node.style.backgroundImage='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))';break;
							}
							if(link=='custom'){
								node.classList.add('transparent');
								game.getDB('image','control_style',function(fileToLoad){
									if(!fileToLoad) return;
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										node.style.backgroundImage='url('+data+')';
										node.className='button character controlbutton';
										node.parentNode.lastChild.classList.add('showdelete');
									};
									fileReader.readAsDataURL(fileToLoad, "UTF-8");
								});
							}
						},
						onclick:function(layout){
							game.saveConfig('control_style',layout);
							if(ui.css.control_stylesheet){
								ui.css.control_stylesheet.remove();
								delete ui.css.control_stylesheet;
							}
							if(layout=='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");
								});
							}
							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<game.players.length;i++){
								if(game.players[i].isLinked()){
									list.push(game.players[i]);
								}
							}
							game.saveConfig('link_style2',style);
							for(var i=0;i<list.length;i++){
								if(get.is.linked2(list[i])){
									list[i].classList.add('linked2');
									list[i].classList.remove('linked');
								}
								else{
									list[i].classList.add('linked');
									list[i].classList.remove('linked2');
								}
							}
							if(style=='chain'){
								ui.arena.classList.remove('nolink');
							}
							else{
								ui.arena.classList.add('nolink');
							}
							ui.updatem();
						}
					},
					cardshape:{
						name:'手牌显示',
						intro:'将手牌设置为正方形或长方形',
						init:'default',
						unfrequent:true,
						item:{
							default:'默认',
							oblong:'长方',
						},
						onclick:function(item){
							var linked=false;
							if(game.me&&game.me.isLinked()){
								linked=true;
							}
							game.saveConfig('cardshape',item);
							if(item=='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(linked){
								if(get.is.linked2(game.me)){
									game.me.classList.remove('linked');
									game.me.classList.add('linked2');
								}
								else{
									game.me.classList.add('linked');
									game.me.classList.remove('linked2');
								}
							}
						}
					},
					cardtempname:{
						name:'视为卡牌名称显示',
						intro:'显示强制视为类卡牌(如武魂),包括拆顺对话框内的判定牌(国色)转换等名称的显示方式',
						init:'image',
						unfrequent:true,
						item:{
							default:'纵向',
							horizon:'横向',
							image:'图片',
							off:'禁用',
						},
						onclick:function(item){
							game.saveConfig('cardtempname',item);
							if(!game.me||!game.me.getCards) return;
							var hs=game.me.getCards('h');
							for(var i=0;i<hs.length;i++){
								if(hs[i]._tempName){
									switch(item){
										case 'default':
										case 'horizon':
										case 'image':
											ui.create.cardTempName(hs[i]);
											break;
										default:
											hs[i]._tempName.delete();
											delete hs[i]._tempName;
									}
								}
							}
						}
					},
					/*textequip:{
						name:'装备显示',
						init:'image',
						unfrequent:true,
						item:{
							image:'图片',
							text:'文字',
						},
						onclick:function(item){
							game.saveConfig('textequip',item);
							if(item=='text'&&(game.layout=='long'||game.layout=='mobile')){
								ui.arena.classList.add('textequip');
							}
							else{
								ui.arena.classList.remove('textequip');
							}
						}
					},*/
					buttoncharacter_style:{
						name:'选将样式',
						init:'default',
						item:{
							default:'默认',
							simple:'精简',
							old:'旧版'
						},
						unfrequent:true,
					},
					buttoncharacter_prefix:{
						name:'武将前缀',
						init:'default',
						item:{
							default:'默认',
							simple:'不显示颜色',
							off:'不显示前缀'
						},
						unfrequent:true,
					},
					cursor_style:{
						name:'鼠标指针',
						init:'auto',
						intro:'设置为固定后鼠标指针将不随移动到的区域而变化',
						unfrequent:true,
						item:{
							auto:'自动',
							pointer:'固定'
						},
						onclick:function(item){
							game.saveConfig('cursor_style',item);
							if(item=='pointer'){
								ui.window.classList.add('nopointer');
							}
							else{
								ui.window.classList.remove('nopointer');
							}
						}
					},
					name_font:{
						name:'人名字体',
						init:'xingkai',
						unfrequent:true,
						item:{},
						textMenu:function(node,link){
							if(link!='default'){
								node.style.fontFamily=link;
							}
							node.style.fontSize='20px';
						},
						onclick:function(font){
							game.saveConfig('name_font',font);
							lib.init.cssstyles();
						}
					},
					identity_font:{
						name:'身份字体',
						init:'huangcao',
						unfrequent:true,
						item:{},
						textMenu:function(node,link){
							if(link!='default'){
								node.style.fontFamily=link;
							}
							node.style.fontSize='20px';
						},
						onclick:function(font){
							game.saveConfig('identity_font',font);
							lib.init.cssstyles();
						}
					},
					cardtext_font:{
						name:'卡牌字体',
						init:'default',
						unfrequent:true,
						item:{},
						textMenu:function(node,link){
							if(link!='default'){
								node.style.fontFamily=link;
							}
							node.style.fontSize='20px';
						},
						onclick:function(font){
							game.saveConfig('cardtext_font',font);
							lib.init.cssstyles();
						}
					},
					global_font:{
						name:'界面字体',
						init:'default',
						unfrequent:true,
						item:{},
						textMenu:function(node,link){
							if(link!='default'){
								node.style.fontFamily=link;
							}
							else{
								node.style.fontFamily="'STHeiti','SimHei','Microsoft JhengHei','Microsoft YaHei','WenQuanYi Micro Hei','Suits',Helvetica,Arial,sans-serif";
							}
							node.style.fontSize='20px';
						},
						onclick:function(font){
							game.saveConfig('global_font',font);
							lib.init.cssstyles();
						}
					},
					suits_font:{
						name:'替换花色字体',
						init:true,
						unfrequent:true,
						intro:'使用全角字符的花色替代系统自带的花色(重启游戏后生效)',
						onclick:function(bool){
							game.saveConfig('suits_font',bool);
						}
					},
					update:function(config,map){
						if(lib.config.custom_button){
							map.custom_button_system_top.show();
							map.custom_button_system_bottom.show();
							map.custom_button_control_top.show();
							map.custom_button_control_bottom.show();
						}
						else{
							map.custom_button_system_top.hide();
							map.custom_button_system_bottom.hide();
							map.custom_button_control_top.hide();
							map.custom_button_control_bottom.hide();
						}
						if(lib.config.change_skin){
							map.change_skin_auto.show();
						}
						else{
							map.change_skin_auto.hide();
						}
						if(lib.config.image_background_random){
							map.image_background_blur.show();
							map.image_background.hide();
							// map.import_background.hide();
						}
						else{
							map.image_background.show();
							if(lib.config.image_background=='default'){
								map.image_background_blur.hide();
							}
							else{
								map.image_background_blur.show();
							}
							// if(lib.config.image_background=='custom'&&lib.db){
							// 	map.import_background.show();
							// }
							// else{
							// 	map.import_background.hide();
							// }
						}
						if(lib.config.layout=='long'||lib.config.layout=='mobile'){
							//map.textequip.show();
							map.cardshape.show();
							map.phonelayout.show();
						}
						else{
							//map.textequip.hide();
							if(lib.config.layout=='long2'||lib.config.layout=='nova'){
								map.phonelayout.show();
								map.cardshape.show();
							}
							else{
								map.phonelayout.hide();
								map.cardshape.hide();
							}
						}
						if(lib.config.layout=='long'){
							// map.fewplayer.show();
							map.player_height.show();
						}
						else{
							// map.fewplayer.hide();
							if(lib.config.layout=='long2'){
								map.player_height.show();
							}
							else{
								map.player_height.hide();
							}
						}
						if(lib.config.layout=='nova'){
							map.player_height_nova.show();
						}
						else{
							map.player_height_nova.hide();
						}
						if(lib.config.touchscreen){
							map.cursor_style.hide();
						}
						else{
							map.cursor_style.show();
						}
						if(lib.config.border_style=='auto'){
							map.autoborder_count.show();
							map.autoborder_start.show();
						}
						else{
							map.autoborder_count.hide();
							map.autoborder_start.hide();
						}
					},
				}
			},
			view:{
				name:'显示',
				config:{
					update:function(config,map){
						if(lib.config.mode=='versus'||lib.config.mode=='chess'||lib.config.mode=='tafang'||lib.config.mode=='boss'){
							map.show_handcardbutton.show();
						}
						else{
							map.show_handcardbutton.hide();
						}
						if(lib.config.touchscreen){
							map.pop_logv.hide();
						}
						else{
							map.pop_logv.show();
						}
						if(lib.device){
							if(lib.device=='android'){
								map.show_statusbar_android.show();
								map.show_statusbar_ios.hide();
							}
							else if(lib.device=='ios'){
								map.show_statusbar_ios.show();
								map.show_statusbar_android.hide();
							}
							if(!game.download){
								setTimeout(function(){
									if(!window.StatusBar){
										map.show_statusbar.hide();
									}
								},5000);
							}
						}
						else{
							map.show_statusbar_ios.hide();
							map.show_statusbar_android.hide();
						}
						if(get.is.phoneLayout()){
							map.remember_round_button.show();
							map.popequip.show();
							map.filternode_button.show();
							map.show_pause.hide();
							map.show_auto.hide();
							map.show_replay.hide();
							map.show_round_menu.show();
						}
						else{
							map.show_pause.show();
							map.show_auto.show();
							map.show_replay.show();
							map.show_round_menu.hide();
							map.remember_round_button.hide();
							map.popequip.hide();
							map.filternode_button.hide();
						}
						if(lib.config.show_card_prompt){
							map.hide_card_prompt_basic.show();
							map.hide_card_prompt_equip.show();
						}
						else{
							map.hide_card_prompt_basic.hide();
							map.hide_card_prompt_equip.hide();
						}
						if(lib.config.show_log!='off'){
							map.clear_log.show();
						}
						else{
							map.clear_log.hide();
						}
						if(get.is.phoneLayout()){
							map.show_time2.show();
							map.show_time.hide();
							if(lib.config.show_time2){
								map.watchface.show();
							}
							else{
								map.watchface.hide();
							}
						}
						else{
							map.show_time2.hide();
							map.show_time.show();
							map.watchface.hide();
						}
						if(lib.config.show_extensionmaker){
							map.show_extensionshare.show();
						}
						else{
							map.show_extensionshare.hide();
						}
					},
					show_history:{
						name:'出牌记录栏',
						init:'off',
						intro:'在屏幕左侧或右侧显示出牌记录',
						unfrequent:true,
						item:{
							off:'关闭',
							left:'靠左',
							right:'靠右',
						},
						onclick:function(bool){
							if(lib.config.show_history=='right') ui.window.animate('rightbar2');
							game.saveConfig('show_history',bool);
							if(_status.video||!_status.prepareArena) return;
							if(bool=='left'){
								ui.window.classList.add('leftbar');
								ui.window.classList.remove('rightbar');
							}
							else if(bool=='right'){
								ui.window.classList.remove('leftbar');
								ui.window.classList.add('rightbar');
							}
							else{
								ui.window.classList.remove('leftbar');
								ui.window.classList.remove('rightbar');
							}
						}
					},
					pop_logv:{
						name:'自动弹出记录',
						init:false,
						unfrequent:true
					},
					show_log:{
						name:'历史记录栏',
						init:'off',
						intro:'在屏幕中部显示出牌文字记录',
						unfrequent:true,
						item:{
							off:'关闭',
							left:'靠左',
							center:'居中',
							right:'靠右',
						},
						onclick:function(bool){
							game.saveConfig('show_log',bool);
							if(lib.config.show_log!='off'){
								ui.arenalog.style.display='';
								ui.arenalog.dataset.position=bool;
							}
							else{
								ui.arenalog.style.display='none';
								ui.arenalog.innerHTML='';
							}
						}
					},
					clear_log:{
						name:'自动清除历史记录',
						init:false,
						unfrequent:true,
						intro:'开启后将定时清除历史记录栏的条目(而不是等记录栏满后再清除)'
					},
					log_highlight:{
						name:'历史记录高亮',
						init:true,
						unfrequent:true,
						intro:'开启后历史记录不同类别的信息将以不同颜色显示',
					},
					show_time:{
						name:'显示时间',
						intro:'在屏幕顶部显示当前时间',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_time',bool);
							if(bool){
								ui.time.style.display='';
							}
							else{
								ui.time.style.display='none';
							}
						}
					},
					show_time2:{
						name:'显示时间',
						intro:'在触屏按钮处显示当前时间',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_time2',bool);
							if(bool){
								ui.roundmenu.classList.add('clock');
							}
							else{
								ui.roundmenu.classList.remove('clock');
							}
						}
					},
					watchface:{
						name:'表盘样式',
						init:'none',
						unfrequent:true,
						item:{
							none:'默认',
							simple:'简约',
						},
						onclick:function(item){
							game.saveConfig('watchface',item);
							ui.roundmenu.dataset.watchface=item;
						}
					},
					show_time3:{
						name:'显示游戏时间',
						init:false,
						unfrequent:true
					},
					show_statusbar_android:{
						name:'显示状态栏',
						init:false,
						unfrequent:true,
						content:function(bool){
							game.saveConfig('show_statusbar',bool);
							if(window.StatusBar&&lib.device=='android'){
								if(bool){
									window.StatusBar.overlaysWebView(false);
									window.StatusBar.backgroundColorByName('black');
									window.StatusBar.show();
								}
								else{
									window.StatusBar.hide();
								}
							}
						}
					},
					show_statusbar_ios:{
						name:'显示状态栏',
						init:'off',
						unfrequent:true,
						item:{
							default:'默认',
							overlay:'嵌入',
							auto:'自动',
							off:'关闭'
						},
						onclick:function(bool){
							game.saveConfig('show_statusbar_ios',bool);
							if(window.StatusBar&&lib.device=='ios'){
								if(bool!='off'&&bool!='auto'){
									if(lib.config.show_statusbar_ios=='default'){
										window.StatusBar.overlaysWebView(false);
										document.body.classList.remove('statusbar');
									}
									else{
										window.StatusBar.overlaysWebView(true);
										document.body.classList.add('statusbar');
									}
									window.StatusBar.backgroundColorByName('black');
									window.StatusBar.show();
								}
								else{
									document.body.classList.remove('statusbar');
									window.StatusBar.hide();
								}
							}
						}
					},
					show_card_prompt:{
						name:'显示出牌信息',
						intro:'出牌时在使用者上显示卡牌名称',
						init:true,
						unfrequent:true,
					},
					hide_card_prompt_basic:{
						name:'隐藏基本牌信息',
						intro:'不显示基本牌名称',
						init:false,
						unfrequent:true,
					},
					hide_card_prompt_equip:{
						name:'隐藏装备牌信息',
						intro:'不显示装备牌名称',
						init:false,
						unfrequent:true,
					},
					show_phase_prompt:{
						name:'显示阶段信息',
						intro:'在当前回合不同阶段开始时显示阶段名称',
						init:true,
						unfrequent:true,
					},
					show_phaseuse_prompt:{
						name:'出牌阶段提示',
						intro:'在你出牌时显示提示文字',
						init:true,
						unfrequent:true,
					},
					auto_popped_config:{
						name:'自动弹出选项',
						intro:'鼠标移至选项按钮时弹出模式选择菜单',
						init:true,
						unfrequent:true,
					},
					auto_popped_history:{
						name:'自动弹出历史',
						intro:'鼠标移至暂停按钮时弹出历史记录菜单',
						init:false,
						unfrequent:true,
					},
					show_round_menu:{
						name:'显示触屏按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							if(get.is.nomenu('show_round_menu',bool)) return false;
							game.saveConfig('show_round_menu',bool);
							if(bool&&ui.roundmenu){
								ui.roundmenu.style.display='';
							}
							else{
								ui.roundmenu.style.display='none';
								alert('关闭触屏按钮后可通过手势打开菜单(默认为下划)')
							}
						}
					},
					remember_round_button:{
						name:'记住按钮位置',
						intro:'重新开始后触屏按钮将保存的上一局的位置',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('remember_round_button',bool);
							if(!bool){
								ui.click.resetround();
							}
						}
					},
					remember_dialog:{
						name:'记住对话框位置',
						intro:'移动对话框后新的对话框也将在移动后的位置显示',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('remember_dialog',bool);
							if(!bool){
								if(ui.dialog){
									var dialog=ui.dialog;
									dialog.style.transform='';
									dialog._dragtransform=[0,0];
									dialog.style.transition='all 0.3s';
									dialog._dragtouches;
									dialog._dragorigin;
									dialog._dragorigintransform;
									setTimeout(function(){
										dialog.style.transition='';
									},500);
								}
								game.saveConfig('dialog_transform',[0,0]);
							}
						}
					},
					transparent_dialog:{
						name:'堆叠对话框虚化',
						init:false,
						intro:'当具有static属性的对话框堆叠(如五谷丰登对话框中提示无懈可击)时,将后方的对话框变为半透明',
						onclick:function(bool){
							game.saveConfig('transparent_dialog',bool);
							if(bool){
								for(var i=0;i<ui.dialogs.length;i++){
									if(ui.dialogs[i]!=ui.dialog&&ui.dialogs[i].static){
										ui.dialogs[i].unfocus();
									}
								}
							}
							else{
								for(var i=0;i<ui.dialogs.length;i++){
									if(ui.dialogs[i]!=ui.dialog&&ui.dialogs[i].static){
										ui.dialogs[i].refocus();
									}
								}
							}
						}
					},
					show_rarity:{
						name:'显示武将评级',
						init:false,
						intro:'仅供娱乐,重启后生效',
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_rarity',bool);
						}
					},
					mark_identity_style:{
						name:'标记身份操作',
						intro:'设置单击身份按钮时的操作',
						unfrequent:true,
						init:'menu',
						item:{
							menu:'菜单',
							click:'单击',
						},
					},
					character_dialog_tool:{
						name:'自由选将显示',
						intro:'点击自由选将时默认显示的条目',
						init:'最近',
						item:{
							'收藏':'收藏',
							'最近':'最近',
							'all':'全部'
						},
						unfrequent:true,
					},
					recent_character_number:{
						name:'最近使用武将',
						intro:'自由选将对话框中最近使用武将的数量',
						init:'12',
						item:{
							'6':'6',
							'12':'12',
							'20':'24',
							'30':'36',
						},
						unfrequent:true
					},
					popequip:{
						name:'触屏装备选择',
						intro:'设置触屏布局中选择装备的方式',
						init:true,
						unfrequent:true,
					},
					filternode_button:{
						name:'触屏筛选按钮',
						intro:'设置自由选将对话框中筛选按钮的样式',
						init:true,
						unfrequent:true,
					},
					show_charactercard:{
						name:'显示武将资料',
						intro:'在武将界面单击时弹出武将资料卡',
						init:true,
						unfrequent:true
					},
					show_favourite:{
						name:'显示添加收藏',
						intro:'在角色的右键菜单中显示添加收藏',
						init:false,
						unfrequent:true
					},
					show_favmode:{
						name:'显示模式收藏',
						intro:'快捷菜单中显示收藏模式',
						init:true,
						unfrequent:true
					},
					show_favourite_menu:{
						name:'显示收藏菜单',
						intro:'在选项-武将中显示收藏一栏',
						init:true,
						unfrequent:true
					},
					show_ban_menu:{
						name:'显示禁将菜单',
						intro:'在选项-武将中显示禁将一栏',
						init:true,
						unfrequent:true
					},
					right_range:{
						name:'显示距离信息',
						intro:'在角色的右键菜单中显示距离等信息',
						init:true,
						unfrequent:true
					},
					hide_card_image:{
						name:'隐藏卡牌背景',
						intro:'所有卡牌将使用文字作为背景',
						init:false,
						unfrequent:true,
						restart:true,
					},
					show_name:{
						name:'显示角色名称',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_name',bool);
							if(bool){
								ui.arena.classList.remove('hide_name');
							}
							else{
								ui.arena.classList.add('hide_name');
							}
						}
					},
					show_sex:{
						name:'显示角色性别',
						intro:'在角色的右键菜单中显示角色性别',
						init:true,
						unfrequent:true
					},
					show_group:{
						name:'显示角色势力',
						intro:'在角色的右键菜单中显示角色势力',
						init:true,
						unfrequent:true
					},
					show_replay:{
						name:'显示重来按钮',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_replay',bool);
							if(lib.config.show_replay){
								ui.replay.style.display='';
							}
							else{
								ui.replay.style.display='none';
							}
						}
					},
					show_playerids:{
						name:'显示身份按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_playerids',bool);
							if(lib.config.show_playerids){
								ui.playerids.style.display='';
							}
							else{
								ui.playerids.style.display='none';
							}
						}
					},
					show_sortcard:{
						name:'显示整理手牌按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_sortcard',bool);
							if(lib.config.show_sortcard){
								ui.sortCard.style.display='';
							}
							else{
								ui.sortCard.style.display='none';
							}
						}
					},
					show_pause:{
						name:'显示暂停按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_pause',bool);
							if(lib.config.show_pause){
								ui.pause.style.display='';
							}
							else{
								ui.pause.style.display='none';
							}
						}
					},
					show_auto:{
						name:'显示托管按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_auto',bool);
							if(lib.config.show_auto){
								ui.auto.style.display='';
							}
							else{
								ui.auto.style.display='none';
							}
						}
					},
					show_volumn:{
						name:'显示音量按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_volumn',bool);
							if(lib.config.show_volumn){
								ui.volumn.style.display='';
							}
							else{
								ui.volumn.style.display='none';
							}
						}
					},
					show_cardpile:{
						name:'显示牌堆按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_cardpile',bool);
							if(bool){
								ui.cardPileButton.style.display='';
							}
							else{
								ui.cardPileButton.style.display='none';
							}
						}
					},
					show_cardpile_number:{
						name:'显示剩余牌数',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_cardpile_number',bool);
							if(bool){
								ui.cardPileNumber.style.display='';
							}
							else{
								ui.cardPileNumber.style.display='none';
							}
						}
					},
					show_handcardbutton:{
						name:'显示手牌按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_handcardbutton',bool);
						}
					},
					show_giveup:{
						name:'显示投降按钮',
						init:true,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_giveup',bool);
						}
					},
					show_wuxie:{
						name:'显示无懈按钮',
						intro:'在右上角显示不询问无懈',
						init:false,
						unfrequent:true,
						onclick:function(bool){
							game.saveConfig('show_wuxie',bool);
							if(lib.config.show_wuxie){
								ui.wuxie.style.display='';
							}
							else{
								ui.wuxie.style.display='none';
							}
						}
					},
					wuxie_right:{
						name:'无懈按钮靠左',
						init:true,
						unfrequent:true,
					},
					show_discardpile:{
						name:'暂停时显示弃牌堆',
						init:false,
						unfrequent:true,
					},
					show_extensionmaker:{
						name:'显示制作扩展',
						init:true,
						unfrequent:true,
					},
					show_extensionshare:{
						name:'显示分享扩展',
						init:true,
						unfrequent:true,
					},
					show_characternamepinyin:{
						name:'显示武将名注解',
						intro:'在武将资料卡显示武将名及其注解、性别、势力、体力等信息',
						init:'showPinyin',
						unfrequent:true,
						item:{
							doNotShow:'不显示',
							showPinyin:'拼音(样式一)',
							showCodeIdentifier:'代码ID(样式一)',
							showPinyin2:'拼音(样式二)',
							showCodeIdentifier2:'代码ID(样式二)',
						},
						visualMenu:(node,link,name)=>{
							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<menu.childElementCount;i++){
								if(!['music_off','music_custom','music_random'].concat(lib.config.all.background_music).contains(menu.childNodes[i]._link)) menu.childNodes[i].delete();
							}
						},
						name:'背景音乐',
						init:true,
						item:{
							music_default:'默认',
						},
						onclick:function(item){
							game.saveConfig('background_music',item);
							game.playBackgroundMusic();
						}
					},
					import_music:{
						name:'<div style="white-space:nowrap;width:calc(100% - 5px)">'+
						'<input type="file" style="width:calc(100% - 40px)" accept="audio/*">'+
						'<button style="width:40px">确定</button></div>',
						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:'<div style="white-space:nowrap;width:calc(100% - 10px)">'+
						'<input type="file" accept="*/*" style="width:calc(100% - 40px)">'+
						'<button style="width:40px">确定</button></div>',
						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;i<lib.config.hiddenCardPack.length;i++){
					//      															pack.add(lib.config.hiddenCardPack[i]);
					//      									  }
					//      						 }
					//      						 for(var i=0;i<pack.length;i++){
					//      									  if(lib.config.all.sgscards.contains(pack[i])){
					//      															pack.splice(i--,1);
					//      									  }
					//      						 }
					// 			game.saveConfig('hiddenCardPack',pack);
					//
					//      						 var pack=lib.config.all.characters.slice(0);
					//      						 if(Array.isArray(lib.config.hiddenCharacterPack)){
					//      									  for(var i=0;i<lib.config.hiddenCharacterPack.length;i++){
					//      															pack.add(lib.config.hiddenCharacterPack[i]);
					//      									  }
					//      						 }
					//      						 for(var i=0;i<pack.length;i++){
					//      									  if(lib.config.all.sgscharacters.contains(pack[i])){
					//      															pack.splice(i--,1);
					//      									  }
					//      						 }
					// 			game.saveConfig('hiddenCharacterPack',pack);
					//
					//      						 var pack=lib.config.all.mode.slice(0);
					//      						 if(Array.isArray(lib.config.hiddenModePack)){
					//      									  for(var i=0;i<lib.config.hiddenModePack.length;i++){
					//      															pack.add(lib.config.hiddenModePack[i]);
					//      									  }
					//      						 }
					//      						 for(var i=0;i<pack.length;i++){
					//      									  if(lib.config.all.sgsmodes.contains(pack[i])){
					//      															pack.splice(i--,1);
					//      									  }
					//      						 }
					// 			game.saveConfig('hiddenModePack',pack);
					//
					// 			var that=this;
					// 			setTimeout(function(){
					// 				that.innerHTML='隐藏非官方扩展包';
					// 			},500);
					// 		}
					// 	},
					// 	clear:true
					// }
				}
			}
		},
		extensionMenu:{
			cardpile:{
				enable:{
					name:'开启',
					init:false,
					restart:true,
				},
				intro:{
					name:'将杀闪等牌在牌堆中的比例维持在与军争牌堆相同,防止开启扩展包后被过多地稀释',
					clear:true,
					nopointer:true,
				},
				sha:{
					name:'杀',
					init:'1',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				huosha:{
					name:'火杀',
					init:'1',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				leisha:{
					name:'雷杀',
					init:'1',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				shan:{
					name:'闪',
					init:'1',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				tao:{
					name:'桃',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				jiu:{
					name:'酒',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				wuxie:{
					name:'无懈可击',
					init:'0.5',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				nanman:{
					name:'南蛮入侵',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				wanjian:{
					name:'万箭齐发',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				guohe:{
					name:'过河拆桥',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				shunshou:{
					name:'顺手牵羊',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				tiesuo:{
					name:'铁索连环',
					init:'0',
					item:{
						'1':'补充全部',
						'0.5':'补充一半',
						'0':'不补充'
					}
				},
				hide:{
					name:'隐藏此扩展',
					clear:true,
					onclick:function(){
						if(this.firstChild.innerHTML=='隐藏此扩展'){
							this.firstChild.innerHTML='此扩展将在重启后隐藏';
							lib.config.hiddenPlayPack.add('cardpile');
							if(!lib.config.prompt_hidepack){
								alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
								game.saveConfig('prompt_hidepack',true);
							}
						}
						else{
							this.firstChild.innerHTML='隐藏此扩展';
							lib.config.hiddenPlayPack.remove('cardpile');
						}
						game.saveConfig('hiddenPlayPack',lib.config.hiddenPlayPack);
					}
				},
			},
			boss:{
				enable:{
					name:'开启',
					init:false,
					restart:true,
					onswitch:function(bool){
						if(bool){
							var storage={boss:{},versus:{},translate:{}};
							var loadversus=function(){
								game.loadModeAsync('versus',function(mode){
									for(var i in mode.translate){
										storage.translate[i]=mode.translate[i];
									}
									for(var i in mode.jiangeboss){
										if(mode.jiangeboss[i][4].contains('bossallowed')){
											storage.versus[i]=mode.jiangeboss[i];
										}
									}
									localStorage.setItem('boss_storage_playpackconfig',JSON.stringify(storage));
								});
							};
							game.loadModeAsync('boss',function(mode){
								for(var i in mode.translate){
									storage.translate[i]=mode.translate[i];
								}
								for(var i in mode.characterPack.mode_boss){
									if(mode.characterPack.mode_boss[i][4].contains('bossallowed')){
										storage.boss[i]=mode.characterPack.mode_boss[i];
									}
								}
								loadversus();
							});
						}
						else{
							localStorage.removeItem('boss_storage_playpackconfig');
						}
					}
				},
				intro:{
					name:'将剑阁和挑战模式的武将添加到其它模式',
					clear:true,
					nopointer:true,
				},
				enableai:{
					name:'随机选将可用',
					init:false
				},
				hide:{
					name:'隐藏此扩展',
					clear:true,
					onclick:function(){
						if(this.firstChild.innerHTML=='隐藏此扩展'){
							this.firstChild.innerHTML='此扩展将在重启后隐藏';
							lib.config.hiddenPlayPack.add('boss');
							if(!lib.config.prompt_hidepack){
								alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
								game.saveConfig('prompt_hidepack',true);
							}
						}
						else{
							this.firstChild.innerHTML='隐藏此扩展';
							lib.config.hiddenPlayPack.remove('boss');
						}
						game.saveConfig('hiddenPlayPack',lib.config.hiddenPlayPack);
					}
				},
			},
			wuxing:{
				enable:{
					name:'开启',
					init:false,
					restart:true,
				},
				intro:{
					name:'每名角色和部分卡牌在游戏开始时随机获得一个属性',
					clear:true,
					nopointer:true,
				},
				num:{
					name:'带属性卡牌',
					init:'0.3',
					item:{
						'0.1':'10%',
						'0.2':'20%',
						'0.3':'30%',
						'0.5':'50%',
					}
				},
				hide:{
					name:'隐藏此扩展',
					clear:true,
					onclick:function(){
						if(this.firstChild.innerHTML=='隐藏此扩展'){
							this.firstChild.innerHTML='此扩展将在重启后隐藏';
							lib.config.hiddenPlayPack.add('wuxing');
							if(!lib.config.prompt_hidepack){
								alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
								game.saveConfig('prompt_hidepack',true);
							}
						}
						else{
							this.firstChild.innerHTML='隐藏此扩展';
							lib.config.hiddenPlayPack.remove('wuxing');
						}
						game.saveConfig('hiddenPlayPack',lib.config.hiddenPlayPack);
					}
				},
			},
			coin:{
				enable:{
					name:'开启',
					init:false,
					restart:true,
					onclick:function(bool){
						if(bool){
							lib.config.plays.add('coin');
						}
						else{
							lib.config.plays.remove('coin');
						}
						game.saveConfig('plays',lib.config.plays);
					}
				},
				intro:{
					name:'每完成一次对局,可获得一定数量的金币;金币可用于购买游戏特效',
					clear:true,
					nopointer:true,
				},
				display:{
					name:'金币显示',
					init:'text',
					item:{
						symbol:'符号',
						text:'文字'
					},
					onclick:function(item){
						game.saveConfig('coin_display_playpackconfig',item);
						if(game.changeCoin) game.changeCoin(0);
					}
				},
				canvas:{
					name:'特效置顶',
					init:false,
					onclick:function(bool){
						game.saveConfig('coin_canvas_playpackconfig',bool);
						if(bool){
							ui.window.classList.add('canvas_top');
						}
						else{
							ui.window.classList.remove('canvas_top');
						}
					}
				},
				hide:{
					name:'隐藏此扩展',
					clear:true,
					onclick:function(){
						if(this.firstChild.innerHTML=='隐藏此扩展'){
							this.firstChild.innerHTML='此扩展将在重启后隐藏';
							lib.config.hiddenPlayPack.add('coin');
							if(!lib.config.prompt_hidepack){
								alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
								game.saveConfig('prompt_hidepack',true);
							}
						}
						else{
							this.firstChild.innerHTML='隐藏此扩展';
							lib.config.hiddenPlayPack.remove('coin');
						}
						game.saveConfig('hiddenPlayPack',lib.config.hiddenPlayPack);
					}
				},
			},
		},
		mode:{
			identity:{
				name:'身份',
				connect:{
					update:function(config,map){
						if(config.connect_identity_mode=='zhong'){
							map.connect_player_number.hide();
							map.connect_limit_zhu.hide();
							map.connect_enhance_zhu.hide();
							map.connect_double_nei.hide();
							map.connect_zhong_card.show();
							map.connect_special_identity.hide();
							map.connect_double_character.show();
						}
						else if(config.connect_identity_mode=='purple'){
							map.connect_player_number.hide();
							map.connect_limit_zhu.hide();
							map.connect_enhance_zhu.hide();
							map.connect_double_nei.hide();
							map.connect_zhong_card.hide();
							map.connect_special_identity.hide();
							map.connect_double_character.hide();
						}
						else{
							map.connect_double_character.show();
							map.connect_player_number.show();
							map.connect_limit_zhu.show();
							map.connect_enhance_zhu.show();
							if(config.connect_player_number!='2'){
								map.connect_double_nei.show();
							}
							else{
								map.connect_double_nei.hide();
							}
							map.connect_zhong_card.hide();

							if(config.connect_player_number=='8'){
								map.connect_special_identity.show();
							}
							else{
								map.connect_special_identity.hide();
							}
						}
					},
					connect_identity_mode:{
						name:'游戏模式',
						init:'normal',
						item:{
							normal:'标准',
							zhong:'明忠',
							purple:'3v3v2',
						},
						restart:true,
						frequent:true,
						intro:'明忠模式和3v3v2模式详见帮助'
					},
					connect_player_number:{
						name:'游戏人数',
						init:'8',
						item:{
							'2':'两人',
							'3':'三人',
							'4':'四人',
							'5':'五人',
							'6':'六人',
							'7':'七人',
							'8':'八人'
						},
						frequent:true,
						restart:true,
					},
					connect_limit_zhu:{
						name:'常备主候选武将数',
						init:'group',
						restart:true,
						item:{
							off:'不限制',
							group:'按势力筛选',
							'4':'四',
							'6':'六',
							'8':'八',
						},
					},
					connect_zhong_card:{
						name:'明忠卡牌替换',
						init:true,
						frequent:true,
						restart:true
					},
					connect_double_nei:{
						name:'双内奸',
						init:false,
						restart:true,
						// frequent:true,
						intro:'开启后游戏中将有两个内奸(内奸胜利条件仍为主内1v1时击杀主公)'
					},
					connect_double_character:{
						name:'双将模式',
						init:false,
						frequent:true,
						restart:true,
					},
					connect_change_card:{
						name:'启用手气卡',
						init:false,
						frequent:true,
						restart:true,
					},
					connect_special_identity:{
						name:'特殊身份',
						init:false,
						restart:true,
						frequent:true,
						intro:'开启后游戏中将增加军师、大将、贼首三个身份'
					},
					// connect_ban_weak:{
					// 	name:'屏蔽弱将',
					// 	init:true,
					// 	restart:true,
					// },
					// connect_ban_strong:{
					// 	name:'屏蔽强将',
					// 	init:false,
					// 	restart:true,
					// },
					connect_enhance_zhu:{
						name:'加强主公',
						init:false,
						restart:true,
						intro:'为主公增加一个额外技能'
					},
				},
				config:{
					update:function(config,map){
						if(config.identity_mode=='zhong'){
							map.player_number.hide();
							map.enhance_zhu.hide();
							map.double_nei.hide();
							map.auto_identity.hide();
							map.choice_zhu.hide();
							map.limit_zhu.hide();
							map.choice_zhong.hide();
							map.choice_nei.hide();
							map.choice_fan.hide();
							map.ban_identity.hide();
							map.ban_identity2.hide();
							map.ban_identity3.hide();
							map.zhong_card.show();
							map.special_identity.hide();
							map.choose_group.show();
							map.change_choice.show();
							map.auto_mark_identity.show();
							map.double_character.show();
							map.free_choose.show();
							map.change_identity.show();
							if(config.double_character){
								map.double_hp.show();
							}
							else{
								map.double_hp.hide();
							}
							map.continue_game.show();
						}
						else if(config.identity_mode=='purple'){
							map.player_number.hide();
							map.enhance_zhu.hide();
							map.double_nei.hide();
							map.auto_identity.hide();
							map.choice_zhu.hide();
							map.limit_zhu.hide();
							map.choice_zhong.hide();
							map.choice_nei.hide();
							map.choice_fan.hide();
							map.ban_identity.hide();
							map.ban_identity2.hide();
							map.ban_identity3.hide();
							map.zhong_card.hide();
							map.special_identity.hide();
							map.double_character.hide();
							map.double_hp.hide();
							map.choose_group.hide();
							map.auto_mark_identity.hide();
							map.change_choice.hide();
							map.free_choose.hide();
							map.change_identity.hide();
							map.continue_game.hide();
						}
						else{
							map.continue_game.show();
							map.player_number.show();
							map.enhance_zhu.show();
							map.auto_identity.show();
							if(config.player_number!='2'){
								map.double_nei.show();
							}
							else{
								map.double_nei.hide();
							}
							map.choice_zhu.show();
							map.limit_zhu.show();
							map.choice_zhong.show();
							map.choice_nei.show();
							map.choice_fan.show();
							map.ban_identity.show();
							if(config.ban_identity=='off'){
								map.ban_identity2.hide();
							}
							else{
								map.ban_identity2.show();
							}
							if(config.ban_identity=='off'||config.ban_identity2=='off'){
								map.ban_identity3.hide();
							}
							else{
								map.ban_identity3.show();
							}
							map.zhong_card.hide();
							map.choose_group.show();
							map.auto_mark_identity.show();
							map.change_choice.show();
							map.free_choose.show();
							map.change_identity.show();
							if(config.player_number=='8'){
								map.special_identity.show();
							}
							else{
								map.special_identity.hide();
							}
							map.double_character.show();
							if(config.double_character){
								map.double_hp.show();
							}
							else{
								map.double_hp.hide();
							}
						}
					},
					identity_mode:{
						name:'游戏模式',
						init:'normal',
						item:{
							normal:'标准',
							zhong:'明忠',
							purple:'3v3v2',
						},
						restart:true,
						frequent:true,
						intro:'明忠模式详见帮助'
					},
					player_number:{
						name:'游戏人数',
						init:'8',
						item:{
							'2':'两人',
							'3':'三人',
							'4':'四人',
							'5':'五人',
							'6':'六人',
							'7':'七人',
							'8':'八人'
						},
						frequent:true,
						restart:true,
					},
					double_nei:{
						name:'双内奸',
						init:false,
						restart:true,
						frequent:true,
						intro:'开启后游戏中将有两个内奸(内奸胜利条件仍为主内1v1时击杀主公)'
					},
					choose_group:{
						name:'神武将选择势力',
						init:true,
						restart:true,
						frequent:true,
						intro:'若开启此选项,选择神武将的玩家需在亮出自己的武将牌之前为自己选择一个势力。'
					},
					nei_fullscreenpop:{
						name:'主内单挑特效',
						intro:'在进入主内单挑时,弹出全屏文字特效',
						init:true,
						unfrequent:true,
					},
					double_character:{
						name:'双将模式',
						init:false,
						frequent:true,
						restart:true,
					},
					special_identity:{
						name:'特殊身份',
						init:false,
						restart:true,
						frequent:true,
						intro:'开启后游戏中将增加军师、大将、贼首三个身份'
					},
					zhong_card:{
						name:'明忠卡牌替换',
						init:true,
						frequent:true,
						restart:true
					},
					double_hp:{
						name:'双将体力上限',
						init:'pingjun',
						item:{
							hejiansan:'和减三',
							pingjun:'平均值',
							zuidazhi:'最大值',
							zuixiaozhi:'最小值',
							zonghe:'相加',
						},
						restart:true,
					},
					auto_identity:{
						name:'自动显示身份',
						item:{
							off:'关闭',
							one:'一轮',
							two:'两轮',
							three:'三轮',
							always:'始终'
						},
						init:'off',
						onclick:function(bool){
							game.saveConfig('auto_identity',bool,this._link.config.mode);
							if(get.config('identity_mode')=='zhong') return;
							var num;
							switch(bool){
								case '一轮':num=1;break;
								case '两轮':num=2;break;
								case '三轮':num=3;break;
								default:num=0;break;
							}
							if(num&!_status.identityShown&&game.phaseNumber>game.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:'无限',
						},
					},
					continue_game:{
						name:'显示再战',
						init:false,
						onclick:function(bool){
							game.saveConfig('continue_game',bool,this._link.config.mode);
							if(get.config('continue_game')&&get.mode()=='identity'){
								if(!ui.continue_game&&_status.over&&!_status.brawl&&!game.no_continue_game){
									ui.continue_game=ui.create.control('再战',game.reloadCurrent);
								}
							}
							else if(ui.continue_game){
								ui.continue_game.close();
								delete ui.continue_game;
							}
						},
						intro:'游戏结束后可选择用相同的武将再进行一局游戏'
					},
					dierestart:{
						name:'死亡后显示重来',
						init:true,
						onclick:function(bool){
							game.saveConfig('dierestart',bool,this._link.config.mode);
							if(get.config('dierestart')&&get.mode()=='identity'){
								if(!ui.restart&&game.me.isDead()&&!_status.connectMode){
									ui.restart=ui.create.control('restart',game.reload);
								}
							}
							else if(ui.restart){
								ui.restart.close();
								delete ui.restart;
							}
						}
					},
					revive:{
						name:'死亡后显示复活',
						init:false,
						onclick:function(bool){
							game.saveConfig('revive',bool,this._link.config.mode);
							if(get.config('revive')&&get.mode()=='identity'){
								if(!ui.revive&&game.me.isDead()){
									ui.revive=ui.create.control('revive',ui.click.dierevive);
								}
							}
							else if(ui.revive){
								ui.revive.close();
								delete ui.revive;
							}
						}
					},
					ban_identity:{
						name:'屏蔽身份',
						init:'off',
						item:{
							off:'关闭',
							zhu:'主公',
							zhong:'忠臣',
							nei:'内奸',
							fan:'反贼',
						},
					},
					ban_identity2:{
						name:'屏蔽身份2',
						init:'off',
						item:{
							off:'关闭',
							zhu:'主公',
							zhong:'忠臣',
							nei:'内奸',
							fan:'反贼',
						},
					},
					ban_identity3:{
						name:'屏蔽身份3',
						init:'off',
						item:{
							off:'关闭',
							zhu:'主公',
							zhong:'忠臣',
							nei:'内奸',
							fan:'反贼',
						},
					},
					ai_strategy:{
						name:'内奸策略',
						init:'ai_strategy_1',
						item:{
							ai_strategy_1:'均衡',
							ai_strategy_2:'偏反',
							ai_strategy_3:'偏忠',
							ai_strategy_4:'酱油',
							ai_strategy_5:'天使',
							ai_strategy_6:'仇主',
						},
						intro:'设置内奸对主忠反的态度'
					},
					difficulty:{
						name:'AI对人类态度',
						init:'normal',
						item:{
							easy:'友好',
							normal:'一般',
							hard:'仇视',
						},
					},
					choice_zhu:{
						name:'主公候选武将数',
						init:'3',
						restart:true,
						item:{
							'3':'三',
							'4':'四',
							'5':'五',
							'6':'六',
							'8':'八',
							'10':'十',
						},
					},
					limit_zhu:{
						name:'常备主候选武将数',
						init:'group',
						restart:true,
						item:{
							off:'不限制',
							group:'按势力筛选',
							'4':'四',
							'6':'六',
							'8':'八',
						},
					},
					choice_zhong:{
						name:'忠臣候选武将数',
						init:'4',
						restart:true,
						item:{
							'3':'三',
							'4':'四',
							'5':'五',
							'6':'六',
							'8':'八',
							'10':'十',
						},
					},
					choice_nei:{
						name:'内奸候选武将数',
						init:'5',
						restart:true,
						item:{
							'3':'三',
							'4':'四',
							'5':'五',
							'6':'六',
							'8':'八',
							'10':'十',
						},
					},
					choice_fan:{
						name:'反贼候选武将数',
						init:'3',
						restart:true,
						item:{
							'3':'三',
							'4':'四',
							'5':'五',
							'6':'六',
							'8':'八',
							'10':'十',
						},
					},
				}
			},
			guozhan:{
				name:'国战',
				connect:{
					connect_guozhan_mode:{
						name:'游戏模式',
						init:'normal',
						item:{
							normal:'势备',
							yingbian:'应变',
							old:'怀旧',
						},
						frequent:true,
						restart:true,
						intro:'<li>势备:默认模式,使用线下《君临天下·势备篇》的牌堆进行游戏。<br><li>应变:使用OL的应变国战牌堆进行游戏。<br><li>怀旧:使用传统国战的牌堆进行游戏。',
					},
					connect_player_number:{
						name:'游戏人数',
						init:'8',
						item:{
							'3':'三人',
							'4':'四人',
							'5':'五人',
							'6':'六人',
							'7':'七人',
							'8':'八人'
						},
						frequent:true,
						restart:true,
					},
					connect_initshow_draw:{
						name:'首亮奖励',
						item:{
							'off':'关闭',
							'draw':'摸牌',
							'mark':'标记',
						},
						init:'mark',
						frequent:true,
						intro:'第一个明置武将牌的角色可获得首亮奖励'
					},
					connect_aozhan:{
						name:'鏖战模式',
						init:true,
						intro:'若开启此选项,则将在游戏中引入“鏖战模式”的规则:<br>当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。<br>◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。<br>注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。',
						frequent:true,
						restart:true,
					},
					connect_viewnext:{
						name:'观看下家副将',
						init:false,
						intro:'若开启此选项,所有的玩家将在挑选武将后,分发起始手牌之前,分别观看自己下家的副将。',
					},
					connect_zhulian:{
						name:'珠联璧合',
						init:true,
						// frequent:true,
						intro:'主将和副将都明置后,若为特定组合,可获得【珠联璧合】标记'
					},
					connect_junzhu:{
						name:'替换君主',
						init:true,
						// frequent:true,
						restart:true,
						intro:'若开启此选项,玩家的第一个回合开始时,若其主武将牌有对应的君主武将牌,则其可以将此武将牌替换为对应的君主武将牌,然后重新调整体力上限。若玩家的体力上限因此增大,则玩家回复等量的体力。'
					},
					connect_change_card:{
						name:'启用手气卡',
						init:false,
						frequent:true,
						restart:true,
					},
					// connect_ban_weak:{
					// 	name:'屏蔽弱将',
					// 	init:false,
					// 	restart:true,
					// },
					// connect_ban_strong:{
					// 	name:'屏蔽强将',
					// 	init:false,
					// 	restart:true,
					// },
				},
				config:{
					update:function(config,map){
						if(config.onlyguozhan){
							map.junzhu.show();
						}
						else{
							map.junzhu.hide();
						}
						ui.aozhan_bgm=map.aozhan_bgm;
						map.aozhan_bgm._link.config.updatex.call(map.aozhan_bgm,[]);
					},
					guozhan_mode:{
						name:'游戏模式',
						init:'normal',
						item:{
							normal:'势备',
							yingbian:'应变',
							old:'怀旧',
							free:'自由',
						},
						frequent:true,
						restart:true,
						intro:'<li>势备:默认模式,使用线下《君临天下·势备篇》的牌堆进行游戏。<br><li>应变:使用OL的应变国战牌堆进行游戏。<br><li>怀旧:使用传统国战的牌堆进行游戏。<br><li>自由:使用玩家的自定义牌堆进行游戏。',
					},
					player_number:{
						name:'游戏人数',
						init:'8',
						item:{
							'3':'三人',
							'4':'四人',
							'5':'五人',
							'6':'六人',
							'7':'七人',
							'8':'八人'
						},
						frequent:true,
						restart:true,
					},
					initshow_draw:{
						name:'首亮奖励',
						item:{
							'off':'关闭',
							'draw':'摸牌',
							'mark':'标记',
						},
						init:'mark',
						frequent:true,
						intro:'第一个明置身份牌的角色可获得摸牌奖励'
					},
					aozhan:{
						name:'鏖战模式',
						init:true,
						frequent:true,
						restart:true,
						intro:'若开启此选项,则将在游戏中引入“鏖战模式”的规则:<br>当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。<br>◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。<br>注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。',
					},
					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;i<menu.childElementCount;i++){
								const link=menu.childNodes[i]._link;
								if(['disabled','random'].includes(link)||!_status.aozhanBGMToRemove.includes(link)) continue;
								_status.aozhanBGMToRemove.remove(link);
								menu.childNodes[i].delete();
							}
						},
						name:'鏖战背景音乐',
						item:{
							disabled:'不启用',
							online:'Online',
							rewrite:'Rewrite',
							chaoming:'潮鸣',
							random:'随机播放',
						},
						init:'rewrite',
						onclick:function(item){
							game.saveConfig('aozhan_bgm',item,this._link.config.mode);
							if(_status._aozhan==true) game.playBackgroundMusic();
						},
					},
					zhulian:{
						name:'珠联璧合',
						init:true,
						// frequent:true,
						intro:'主将和副将都明置后,若为特定组合,可获得【珠联璧合】标记'
					},
					changeViceType:{
						name:'副将变更方式',
						init:'default',
						item:{
							default:'发现式',
							online:'随机式',
						},
						frequent:true,
						restart:true,
					},
					onlyguozhan:{
						name:'使用国战武将',
						init:true,
						frequent:true,
						restart:true,
						intro:'开启武将技能将替换为国战版本并禁用非国战武将'
					},
					guozhanSkin:{
						name:'使用国战皮肤',
						init:true,
						frequent:true,
						restart:true,
						intro:'开启此选项后,将会把有国战专属皮肤的武将替换为国战皮肤'
					},
					junzhu:{
						name:'替换君主',
						init:true,
						// frequent:true,
						restart:true,
						intro:'若开启此选项,玩家的第一个回合开始时,若其主武将牌有对应的君主武将牌,则其可以将此武将牌替换为对应的君主武将牌,然后重新调整体力上限。若玩家的体力上限因此增大,则玩家回复等量的体力。'
					},
					double_hp:{
						name:'双将体力上限',
						init:'pingjun',
						item:{
							hejiansan:'和减三',
							pingjun:'平均值',
							zuidazhi:'最大值',
							zuixiaozhi:'最小值',
							zonghe:'相加',
						},
						restart:true,
					},
					// ban_weak:{
					// 	name:'屏蔽弱将',
					// 	init:true,
					// 	restart:true,
					// },
					// ban_strong:{
					// 	name:'屏蔽强将',
					// 	init:false,
					// 	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;
							}
						}
					},
					onlyguozhanexpand:{
						name:'默认展开自由选将',
						init:false,
						restart:true,
						intro:'开启后自由选将对话框将默认显示全部武将'
					},
					change_identity:{
						name:'自由选择座位',
						init:true,
						onclick:function(bool){
							game.saveConfig('change_identity',bool,this._link.config.mode);
							if(get.mode()!='guozhan'||!_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()!='guozhan'||!_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:true,
						intro:'游戏结束后可选择用相同的武将再进行一局游戏',
						onclick:function(bool){
							game.saveConfig('continue_game',bool,this._link.config.mode);
							if(get.config('continue_game')&&get.mode()=='guozhan'){
								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;
							}
						}
					},
					dierestart:{
						name:'死亡后显示重来',
						init:true,
						onclick:function(bool){
							game.saveConfig('dierestart',bool,this._link.config.mode);
							if(get.config('dierestart')&&get.mode()=='guozhan'){
								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()=='guozhan'){
								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;
							}
						}
					},
					difficulty:{
						name:'AI对人类态度',
						init:'normal',
						item:{
							easy:'友好',
							normal:'一般',
							hard:'仇视',
						}
					},
					choice_num:{
						name:'候选武将数',
						init:'7',
						restart:true,
						item:{
							'5':'五',
							'6':'六',
							'7':'七',
							'8':'八',
							'9':'九',
							'10':'十',
						}
					},
				}
			},
			versus:{
				name:'对决',
				connect:{
					update:function(config,map){
						if(config.connect_versus_mode=='1v1'){
							map.connect_choice_num.show();
							map.connect_replace_number.show();
						}
						else{
							map.connect_choice_num.hide();
							map.connect_replace_number.hide();
						}
						if(config.connect_versus_mode=='2v2'||config.connect_versus_mode=='3v3'){
							map.connect_replace_handcard.show();
						}
						else{
							map.connect_replace_handcard.hide();
						}
					},
					connect_versus_mode:{
						name:'游戏模式',
						init:'1v1',
						item:{
							'1v1':'1v1',
							'2v2':'2v2',
							'3v3':'3v3',
							'4v4':'4v4',
							'guandu':'官渡',
						},
						frequent:true
					},
					connect_replace_handcard:{
						name:'四号位保护',
						init:true,
						frequent:true,
						intro:'最后行动的角色起始手牌数+1'
					},
					connect_choice_num:{
						name:'侯选武将数',
						init:'20',
						frequent:true,
						item:{
							'12':'12人',
							'16':'16人',
							'20':'20人',
							'24':'24人',
							'40':'40人',
						}
					},
					connect_replace_number:{
						name:'替补人数',
						init:'2',
						frequent:true,
						item:{
							'0':'无',
							'1':'1人',
							'2':'2人',
							'3':'3人',
							'4':'4人',
							'5':'5人',
						}
					},
					// connect_ban_weak:{
					// 	name:'屏蔽弱将',
					// 	init:true,
					// 	restart:true,
					// },
					// connect_ban_strong:{
					// 	name:'屏蔽强将',
					// 	init:false,
					// 	restart:true,
					// },
				},
				config:{
					update:function(config,map){
						if(config.versus_mode=='four'){
							map.change_choice.hide();
							map.ladder.show();
							if(config.ladder){
								map.ladder_monthly.show();
								map.ladder_reset.show();
							}
							else{
								map.ladder_monthly.hide();
								map.ladder_reset.hide();
							}
							map.enable_all.show();
							map.enable_all_cards_four.show();
							map.four_assign.show();
							map.four_phaseswap.show();
							map.expand_dialog.show();
							map.fouralign.show();
							map.edit_character_four.show();
							map.reset_character_four.show();
						}
						else{
							map.change_choice.show();
							map.ladder.hide();
							map.ladder_monthly.hide();
							map.ladder_reset.hide();
							map.enable_all.hide();
							map.enable_all_cards_four.hide();
							map.four_assign.hide();
							map.four_phaseswap.hide();
							map.expand_dialog.hide();
							map.fouralign.hide();
							map.edit_character_four.hide();
							map.reset_character_four.hide();
						}
						if(config.versus_mode=='three'){
							map.edit_character_three.show();
							map.reset_character_three.show();
						}
						else{
							map.edit_character_three.hide();
							map.reset_character_three.hide();
						}
						if(config.versus_mode=='three'||config.versus_mode=='one'){
							map.enable_all_three.show();
							map.enable_all_cards.show();
						}
						else{
							map.enable_all_three.hide();
							map.enable_all_cards.hide();
						}
						if(config.versus_mode=='jiange'||config.versus_mode=='two'||config.versus_mode=='endless'||
							config.versus_mode=='three'||config.versus_mode=='one'||config.versus_mode=='siguo'){
							map.free_choose.show();
						}
						else{
							map.free_choose.hide();
						}
						if(config.versus_mode=='jiange'){
							map.double_character_jiange.show();
						}
						else{
							map.double_character_jiange.hide();
						}
						if(config.versus_mode=='two'){
							map.replace_handcard_two.show();
							map.replace_character_two.show();
							map.two_assign.show();
							map.two_phaseswap.show();
						}
						else{
							map.replace_handcard_two.hide();
							map.replace_character_two.hide();
							map.two_assign.hide();
							map.two_phaseswap.hide();
						}
						if(config.versus_mode=='two'||config.versus_mode=='siguo'||config.versus_mode=='four'){
							if(config.versus_mode=='four'&&(config.four_assign||config.four_phaseswap)){
								map.change_identity.hide();
							}
							else{
								map.change_identity.show();
							}
						}
						else{
							map.change_identity.hide();
						}
						if(config.versus_mode=='siguo'){
							map.siguo_character.show();
						}
						else{
							map.siguo_character.hide();
						}
					},
					versus_mode:{
						name:'游戏模式',
						init:'four',
						item:{
							four:'对抗',
							three:'统率',
							two:'欢乐',
							guandu:'官渡',
							jiange:'剑阁',
							siguo:'四国',
							standard:'自由'
							// endless:'无尽',
							// triple:'血战',
							// one:'<span style="display:inline-block;width:100%;text-align:center">1v1</span>',
						},
						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;i<map.length;i++){
								str+='"'+map[i]+'",';
								if(i+1<map.length&&(i+1)%5==0) str+='\n    ';
							}
							str+='\n];';
							node.code=str;
							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(!Array.isArray(character)){
										throw('err');
									}
								}
								catch(e){
									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_three',character,'versus');
								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_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;i<map.length;i++){
								str+='"'+map[i]+'",';
								if(i+1<map.length&&(i+1)%5==0) str+='\n    ';
							}
							str+='\n];';
							node.code=str;
							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(!Array.isArray(character)){
										throw('err');
									}
								}
								catch(e){
									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_four',character,'versus');
								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_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协议来连接到联机服务器。<br>请不要轻易勾选此项!',
					},
				}
			},
			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
					},
					qunxionggeju:{
						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:{
			'关于游戏':'<div style="margin:10px">关于无名杀</div><ul style="margin-top:0"><li>无名杀官方发布地址仅有GitHub仓库!<br><a href="https://github.com/libccy/noname">点击前往Github仓库</a><br><li>无名杀基于GPLv3开源协议。<br><a href="https://www.gnu.org/licenses/gpl-3.0.html">点击查看GPLv3协议</a><br><li>其他所有的所谓“无名杀”社群(包括但不限于绝大多数“官方”QQ群、QQ频道等)均为玩家自发组织,与无名杀官方无关!',
			'游戏操作':'<ul><li>长按/鼠标悬停/右键单击显示信息。<li>触屏模式中,双指点击切换暂停;下划显示菜单,上划切换托管。<li>键盘快捷键<br>'+
			'<table><tr><td>A<td>切换托管<tr><td>W<td>切换不询问无懈<tr><td>空格<td>暂停</table><li>编辑牌堆<br>在卡牌包中修改牌堆后,将自动创建一个临时牌堆,在所有模式中共用,当保存当前牌堆后,临时牌堆被清除。每个模式可设置不同的已保存牌堆,设置的牌堆优先级大于临时牌堆。</ul>',
			'游戏命令':'<div style="margin:10px">变量名</div><ul style="margin-top:0"><li>场上角色<br>game.players<li>阵亡角色<br>game.dead'+
			'<li>玩家<br>game.me<li>玩家的上/下家<br>game.me.previous/next'+
			'<li>玩家的上/下家(含阵亡)<br>game.me.previousSeat/<br>nextSeat'+
			'<li>牌堆<br>ui.cardPile<li>弃牌堆<br>ui.discardPile</ul>'+
			'<div style="margin:10px">角色属性</div><ul style="margin-top:0"><li>体力值<br>player.hp'+
			'<li>体力上限<br>player.maxHp<li>身份<br>player.identity<li>手牌<br>player.getCards("h")<li>装备牌<br>player.getCards("e")<li>判定牌<br>player.getCards("j")'+
			'<li>是否存活/横置/翻面<br>player.isAlive()/<br>isLinked()/<br>isTurnedOver()</ul>'+
			'<div style="margin:10px">角色操作</div><ul style="margin-top:0"><li>受到伤害<br>player.damage(source,<br>num)'+
			'<li>回复体力<br>player.recover(num)<li>摸牌<br>player.draw(num)<li>获得牌<br>player.gain(cards)<li>弃牌<br>player.discard(cards)'+
			'<li>使用卡牌<br>player.useCard(card,<br>targets)<li>死亡<br>player.die()<li>复活<br>player.revive(hp)</ul>'+
			'<div style="margin:10px">游戏操作</div><ul style="margin-top:0"><li>在命令框中输出结果<br>game.print(str)<li>清除命令框中的内容<br>cls<li>上一条/下一条输入的内容<br>up/down<li>游戏结束<br>game.over(bool)'+
			'<li>角色资料<br>lib.character<li>卡牌资料<br>lib.card</ul>',
			'游戏名词':'<ul><li>智囊:无名杀默认为过河拆桥/无懈可击/无中生有/洞烛先机。牌堆中没有的智囊牌会被过滤。可在卡牌设置中自行增减。若没有可用的智囊,则改为随机选取的三种锦囊牌的牌名。'+
			'<li>仁库:部分武将使用的游戏外共通区域。至多包含六张牌。当有新牌注入后,若牌数超过上限,则将最早进入仁库的溢出牌置入弃牌堆。'+
			'<li>护甲:和体力类似,每点护甲可抵挡一点伤害,但不影响手牌上限。'+
			'<li>随从:通过技能获得,拥有独立的技能、手牌区和装备区(共享判定区),出场时替代主武将的位置;随从死亡时自动切换回主武将。'+
			'<li>发现:从三张随机亮出的牌中选择一张,若无特殊说明,则获得此牌。'+
			'<li>蓄能技:发动时可以增大黄色的数字。若如此做,红色数字于技能的结算过程中改为原来的两倍。'+
			'<li>施法:若技能的拥有者未拥有等待执行的同名“施法”效果,则其可以发动“施法”技能。其须选择声明一个数字X(X∈[1, 3]),在此之后的第X个回合结束时,其执行“施法”效果,且效果中的数字X视为与技能发动者声明的X相同。'+
			'<li>共同拼点:一种特殊的拼点结算。发起者与被指定的拼点目标同时亮出拼点牌,进行一次决算:其中拼点牌点数唯一最大的角色赢,其他角色均没赢;若没有点数唯一最大的拼点牌,则所有角色拼点均没赢。'+
			'<li>强令:若一名角色拥有带有“强令”的技能,则该技能的发动时机为“出牌阶段开始时”。若技能拥有者发动该技能,其须发布“强令”给一名其他角色,并在对应技能的时间节点加以判断目标角色是否成功完成该强令所要求的任务条件。成功或失败则会根据技能效果执行不同结算流程。'+
			'<li>摧坚:若一名角色拥有带有“摧坚”的技能,则该技能的发动时机为“当你使用伤害牌指定第一个目标后”。你可以对其中一个目标发动“摧坚”技能,然后执行后续效果。其中,后续效果里的X等于该目标的非charlotte技能的数量。'+
			'<li>妄行:一种特殊的选项。若一名角色拥有带有“妄行”的技能,则该技能触发时,你须选择声明一个数字X(X∈{1,2,3,4}),技能后续中的X即为你选择的数字。选择完毕后,你获得如下效果:回合结束时,你选择一项:1.弃置X张牌;2.减1点体力上限。'+
			'<li>搏击:若一名角色拥有带有“搏击”的技能,则当该搏击技能触发时,若本次技能的目标角色在你攻击范围内,且你在其攻击范围内,则你执行技能主体效果时,同时额外执行“搏击”后的额外效果。'+
			'<li>游击:若一名角色拥有带有“游击”的技能,则当该游击技能执行至“游击”处时,若本次技能的目标角色在你的攻击范围内,且你不在其攻击范围内,则你可以执行“游击”后的额外效果。'+
			'<li>激昂:一名角色发动“昂扬技”标签技能后,此技能失效,直至从此刻至满足此技能“激昂”条件后。'+
			''
		},
		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("Invalid or unexpected token")){
					newMessage="查询无效或意外的标记,可能是字符串的引号不成对,错误使用了转义序列,字符串在多行中解析异常";
				}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.documentZoom<ui.window.offsetWidth/2){
				dialog.style.left=(e.clientX/game.documentZoom+10)+'px';
			}
			else{
				dialog.style.left=(e.clientX/game.documentZoom-dialog.offsetWidth-10)+'px';
			}
			var idealtop=(e.clientY||0)/game.documentZoom-dialog.offsetHeight/2;
			if(typeof idealtop!='number'||isNaN(idealtop)||idealtop<=5){
				idealtop=5;
			}
			else if(idealtop+dialog.offsetHeight+10>ui.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;i<lib.canvasUpdates.length;i++){
				ctx.restore();
				ctx.save();
				var update=lib.canvasUpdates[i];
				if(!update.starttime){
					update.starttime=time;
				}
				if(update(time-update.starttime,ctx)===false){
					lib.canvasUpdates.splice(i--,1);
				}
			}
		},
		run:function(time){
			lib.status.time=time;
			for(var i=0;i<lib.updates.length;i++){
				if(!lib.updates[i].hasOwnProperty('_time')){
					lib.updates[i]._time=time;
				}
				if(lib.updates[i](time-lib.updates[i]._time-lib.status.delayed)===false){
					lib.updates.splice(i--,1);
				}
			}
			if(lib.updates.length){
				lib.status.frameId=requestAnimationFrame(lib.run);
			}
			else{
				lib.status.time=0;
				lib.status.delayed=0;
			}
		},
		getUTC:function(date){
			return date.getTime();
		},
		saveVideo:function(){
			if(_status.videoToSave){
				game.export(lib.init.encode(JSON.stringify(_status.videoToSave)),
				'无名杀 - 录像 - '+_status.videoToSave.name[0]+' - '+_status.videoToSave.name[1]);
			}
		},
		genAsync:fn=>gnc.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<arguments.length;++i) if(arguments[i]!==arguments[0])return false;
				return true;
			},
			equalAny:function(){
				if(arguments.length==0) return false;
				if(arguments.length==1) return true;
				for(let i=1;i<arguments.length;++i) if(arguments[i]===arguments[0])return true;
				return false;
			},
			notEquals:function(){
				if(arguments.length==0) return false;
				if(arguments.length==1) return true;
				for(let i=1;i<arguments.length;++i) if(arguments[i]===arguments[0])return false;
				return true;
			},
			notEqualAny:function(){
				if(arguments.length==0) return false;
				if(arguments.length==1) return true;
				for(let i=1;i<arguments.length;++i) if(arguments[i]!==arguments[0])return true;
				return false;
			},
			typeEquals:function(){
				if(arguments.length==0)return false;
				if(arguments.length==1)return arguments[0]!==null;
				const type=typeof arguments[0];
				for(let i=1;i<arguments.length;++i) if(type!==arguments[i])return false;
				return true;
			}
		},
		creation:{
			get array(){
				return [];
			},
			get object(){
				return {};
			},
			get nullObject(){
				return Object.create(null);
			},
			get string(){
				return "";
			}
		},
		linq:{
			cselector:{
				hasAttr:name=>`[${name}]`,
				isAttr:(name,item)=>`[${name}=${item}]`,
				inAttr:(name,item)=>`[${name}~=${item}]`,
				conAttr:(name,item)=>`[${name}*=${item}]`,
				onAttr:(name,item)=>`[${name}|=${item}]`,
				bgnAttr:(name,item)=>`[${name}^=${item}]`,
				endAttr:(name,item)=>`[${name}^=${item}]`,
				merge:function(){return Array.from(arguments).join(" ");},
				of:function(){return Array.from(arguments).join("");},
				class:function(){return `.${Array.from(arguments).join(".")}`;},
				group:function(){return Array.from(arguments).join(",");},
				media:type=>`@media ${type}`
			},
			dom:{
				attributes:{
					style(name,value){
						return {
							_type:"style",
							name:name,
							value:value
						}
					}
				},
				inject(element,options){
					//处理id和class
					if(options.identity){
						for(const item of options.identity){
							if (item.startsWith("#")) element.id = item.slice(1);
							else element.classList.add(item);
						}
					}
					//处理属性
					if(options.attributes){
						for(const item in options.attributes) element.setAttribute(item,options.attributes[item]);
					}
					//处理样式
					if(options.style){
						for(const item in options.style) element.style[item] = options.style[item];
					}
					//处理内容
					if(options.content){
						element.innerHTML=options.content;
					}
					//处理子元素
					if(options.childs){
						for(const item of options.childs){
							element.appendChild(item);
						}
					}
					return element;
				},
				generate(){
					let result=lib.creation.nullObject;
					const args=Array.from(arguments);
					for(const item of args) {
						switch(typeof item) {
							case "object":
								switch (item.constructor) {
									case Object:
									case null:
										if("_type" in item){
											const type=item["_type"];
											if(!(type in result)) result[type]=lib.creation.nullObject;
											result[type][item.name]=item.value;
										}
										else{
											if(!("style" in result)) result.style=lib.creation.nullObject;
											for(const name in item){
												result.style[name]=item[name];
											}
										}
										break;
									default:
										if(!("childs" in result)) result.childs=lib.creation.array;
										result.childs.add(item);
										break;
								}
								break;
							case "string":
								if(/^\.|#/.test(item)){
									if(!("identity" in result)) result.identity=lib.creation.array;
									const identities=item.split(".").filter(Boolean);
									for(const item of identities) result.identity.add(item);
								}
								else result.content = item;
								break;
						}
					}
					return result;
				},
				attribute(name,value){
					return {
						_type:"attributes",
						name:name,
						value:value
					}
				},
				div(){
					const dom=lib.linq.dom;
					return dom.inject(document.createElement("div"),dom.generate(...arguments));
				}
			}
		},
		init:{
			init:function(){
				if(typeof __dirname==='string'&&__dirname.length){
					var dirsplit=__dirname.split('/');
					for(var i=0;i<dirsplit.length;i++){
						if(dirsplit[i]){
							var c=dirsplit[i][0];
							lib.configprefix+=/[A-Z]|[a-z]/.test(c)?c:'_';
						}
					}
					lib.configprefix+='_';
				}
				window.resetGameTimeout=setTimeout(lib.init.reset,parseInt(localStorage.getItem(lib.configprefix+'loadtime'))||10000);
				if(window.cordovaLoadTimeout){
					clearTimeout(window.cordovaLoadTimeout);
					delete window.cordovaLoadTimeout;
				}
				var links=document.head.querySelectorAll('link');
				for(var i=0;i<links.length;i++){
					if(links[i].href.includes('app/color.css')){
						links[i].remove();
						break;
					}
				}
				var index=window.location.href.indexOf('index.html?server=');
				if(index!=-1){
					window.isNonameServer=window.location.href.slice(index+18);
					window.nodb=true;
				}
				else{
					index=localStorage.getItem(lib.configprefix+'asserver');
					if(index){
						window.isNonameServer=index;
						window.isNonameServerIp=lib.hallURL;
					}
				}

				var htmlbg=localStorage.getItem(lib.configprefix+'background');
				if(htmlbg){
					if(htmlbg[0]=='['){
						try{
							htmlbg=JSON.parse(htmlbg);
							htmlbg=htmlbg[get.rand(htmlbg.length)];
							if(htmlbg.startsWith('custom_')){
								throw('err');
							}
							_status.htmlbg=htmlbg;
						}
						catch(e){
							htmlbg=null;
						}
					}
					if(htmlbg){
						document.documentElement.style.backgroundImage='url("'+lib.assetURL+'image/background/'+htmlbg+'.jpg")';
						document.documentElement.style.backgroundSize='cover';
						document.documentElement.style.backgroundPosition='50% 50%';
					}
				}

				lib.get=get;
				lib.ui=ui;
				lib.ai=ai;
				lib.game=game;
				for(let i in lib.element.event){
					_status.event[i]=lib.element.event[i];
				}

				HTMLDivElement.prototype.animate=function(name,time){
					var that;
					if(get.is.mobileMe(this)&&name=='target'){
						that=ui.mebg;
					}
					else{
						that=this;
					}
					that.classList.add(name);
					setTimeout(function(){
						that.classList.remove(name);
					},time||1000);
					return this;
				};
				HTMLDivElement.prototype.hide=function(){
					this.classList.add('hidden');
					return this;
				};
				HTMLDivElement.prototype.unfocus=function(){
					if(lib.config.transparent_dialog) this.classList.add('transparent');
					return this;
				};
				HTMLDivElement.prototype.refocus=function(){
					this.classList.remove('transparent');
					return this;
				};
				HTMLDivElement.prototype.show=function(){
					this.classList.remove('hidden');
					return this;
				};
				HTMLDivElement.prototype.delete=function(time,callback){
					if(this.timeout){
						clearTimeout(this.timeout);
						delete this.timeout;
					}
					if(!this._listeningEnd||this._transitionEnded){
						if(typeof time!='number') time=500;
						this.classList.add('removing');
						var that=this;
						this.timeout=setTimeout(function(){
							that.remove();
							that.classList.remove('removing');
							if(typeof callback=='function'){
								callback();
							}
						},time);
					}
					else{
						this._onEndDelete=true;
					}
					return this;
				};
				HTMLDivElement.prototype.goto=function(position,time){
					if(this.timeout){
						clearTimeout(this.timeout);
						delete this.timeout;
					}

					if(typeof time!='number') time=500;
					this.classList.add('removing');

					var that=this;
					this.timeout=setTimeout(function(){
						if(!that.destroyed){
							position.appendChild(that);
						}
						that.classList.remove('removing');
						delete that.destiny;
					},time);
					this.destiny=position;
					return this;
				};
				HTMLDivElement.prototype.fix=function(){
					clearTimeout(this.timeout);
					delete this.timeout;
					delete this.destiny;
					this.classList.remove('removing');
					return this;
				};
				Object.defineProperty(HTMLDivElement.prototype,'setBackground',{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(name,type,ext,subfolder){
						if(!name) return;
						let src;
						if(ext=='noskin') ext='.jpg';
						ext=ext||'.jpg';
						subfolder=subfolder||'default';
						if(type){
							let dbimage=null,extimage=null,modeimage=null,nameinfo,gzbool=false;
							const mode=get.mode();
							if(type=='character'){
								if(lib.characterPack[`mode_${mode}`]&&lib.characterPack[`mode_${mode}`][name]){
									if(mode=='guozhan'){
										nameinfo=lib.character[name];
										if(name.startsWith('gz_shibing')) name=name.slice(3,11);
										else{
											if(lib.config.mode_config.guozhan.guozhanSkin&&lib.character[name]&&lib.character[name][4].contains('gzskin')) gzbool=true;
											name=name.slice(3);
										}
									}
									else modeimage=mode;
								}
								else if(name.includes('::')){
									name=name.split('::');
									modeimage=name[0];
									name=name[1];
								}
								else{
									nameinfo=get.character(name);
								}
							}
							if(!modeimage&&nameinfo&&nameinfo[4]) for(const value of nameinfo[4]){
								if(value.startsWith('ext:')){
									extimage=value;
									break;
								}
								else if(value.startsWith('db:')){
									dbimage=value;
									break;
								}
								else if(value.startsWith('mode:')){
									modeimage=value.slice(5);
									break;
								}
								else if(value.startsWith('character:')){
									name=value.slice(10);
									break;
								}
							}
							if(extimage) src=extimage.replace(/^ext:/,'extension/');
							else if(dbimage){
								this.setBackgroundDB(dbimage.slice(3));
								return this;
							}
							else if(modeimage) src=`image/mode/${modeimage}/character/${name}${ext}`;
							else if(type=='character'&&lib.config.skin[name]&&arguments[2]!='noskin') src=`image/skin/${name}/${lib.config.skin[name]}${ext}`;
							else if(type=='character') src=`image/character/${gzbool?'gz_':''}${name}${ext}`;
							else src=`image/${type}/${subfolder}/${name}${ext}`;
						}
						else src=`image/${name}${ext}`;
						this.setBackgroundImage(src);
						this.style.backgroundPositionX='center';
						this.style.backgroundSize='cover';
						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;i<arguments.length;i++) position.push(arguments[i]);
					}
					else if(arguments.length==1&&Array.isArray(arguments[0])&&arguments[0].length==4){
						position=arguments[0];
					}
					else{
						return this;
					}
					var top='calc('+position[0]+'% ';
					if(position[1]>0) 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(row<this.childNodes.length){
						return this.childNodes[row].childNodes[col];
					}
				};
				/*处理lib.nature的兼容性问题*/
				const mapHasFunc=function(item){
					return this.has(item)
				};
				Object.defineProperty(Map.prototype, "contains",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:mapHasFunc
				});
				Object.defineProperty(Map.prototype, "includes",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:mapHasFunc
				});
				const mapAddFunc=function(item){
					this.set(item,0);
					return this;
				}
				Object.defineProperty(Map.prototype, "add", {
					configurable:true,
					enumerable:false,
					writable:true,
					value:mapAddFunc
				});
				Object.defineProperty(Map.prototype, "push", {
					configurable:true,
					enumerable:false,
					writable:true,
					value:mapAddFunc
				});
				Object.defineProperty(Map.prototype, "addArray", {
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(arr){
						for(var i=0;i<arr.length;i++){
							this.add(arr[i]);
						}
						return this;
					}
				});
				Object.defineProperty(Map.prototype, "remove", {
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(item){
						this.delete(item);
						return this;
					}
				});
				/*Map prototype end*/
				Object.defineProperty(Array.prototype,"filterInD",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(pos){
						if(typeof pos!='string') pos='o';
						return this.filter(card=>pos.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 `Array.prototype.includes(searchElement)` 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;i<uniqueArray.length;i++) this[i]=uniqueArray[i];
						return this;
					}
				});
				Object.defineProperty(Array.prototype,"toUniqued",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(){
						return [...new Set(this)];
					}
				});
				Object.defineProperty(Array.prototype,"randomGet",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(){
						let arr=this.slice(0);
						arr.removeArray(Array.from(arguments));
						return arr[Math.floor(Math.random()*arr.length)];
					}
				});
				Object.defineProperty(Array.prototype,"randomGets",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(num){
						if(num>this.length) num=this.length;
						let arr=this.slice(0);
						let list=[];
						for(let i=0;i<num;i++){
							list.push(arr.splice(Math.floor(Math.random()*arr.length),1)[0]);
						}
						return list;
					}
				});
				Object.defineProperty(Array.prototype,"randomRemove",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(num){
						if(typeof num=='number'){
							let list=[];
							for(let i=0;i<num;i++){
								if(!this.length) break;
								list.push(this.randomRemove());
							}
							return list;
						}
						return this.splice(Math.floor(Math.random()*this.length),1)[0];
					}
				});
				Object.defineProperty(Array.prototype,"randomSort",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(){
						let list=[];
						while(this.length){
							list.push(this.randomRemove());
						}
						for(let i=0;i<list.length;i++){
							this.push(list[i]);
						}
						return this;
					}
				});
				Object.defineProperty(Array.prototype,"sortBySeat",{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(target){
						lib.tempSortSeat=target;
						this.sort(lib.sort.seat);
						delete lib.tempSortSeat;
						return this;
					}
				});
				/**
				*@description 从数组中寻找某个特征最大的,且通过筛选的第一个元素
				 */
				Object.defineProperty(Array.prototype,"maxBy",{
					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[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];
					}
				});
				//!!!WARNING!!!
				//Will be deprecated in next verision
				Object.defineProperty(Object.prototype,'hasNature',{
					configurable:true,
					enumerable:false,
					writable:true,
					value:function(nature,player){
						var natures=get.natureList(this,player);
						if(!nature) return natures.length>0;
						if(nature=='linked') return natures.some(n=>lib.linked.includes(n));
						return get.is.sameNature(natures,nature);
					}
				});
				window.onkeydown=function(e){
					if(!ui.menuContainer||!ui.menuContainer.classList.contains('hidden')){
						if(e.keyCode==116||((e.ctrlKey||e.metaKey)&&e.keyCode==82)){
							if(e.shiftKey){
								if(confirm('是否重置游戏?')){
									var noname_inited=localStorage.getItem('noname_inited');
									var onlineKey=localStorage.getItem(lib.configprefix+'key');
									localStorage.clear();
									if(noname_inited){
										localStorage.setItem('noname_inited',noname_inited);
									}
									if(onlineKey){
										localStorage.setItem(lib.configprefix+'key',onlineKey);
									}
									if(indexedDB) indexedDB.deleteDatabase(lib.configprefix+'data');
									game.reload();
									return;
								}
							}
							else{
								game.reload();
							}
						}
						else if(e.keyCode==83&&(e.ctrlKey||e.metaKey)){
							if(window.saveNonameInput){
								window.saveNonameInput();
							}
							e.preventDefault();
							e.stopPropagation();
							return false;
						}
						else if(e.keyCode==74&&(e.ctrlKey||e.metaKey)&&lib.node){
							lib.node.debug();
						}
					}
					else{
						game.closePopped();
						var dialogs=document.querySelectorAll('#window>.dialog.popped:not(.static)');
						for(var i=0;i<dialogs.length;i++){
							dialogs[i].delete();
						}
						if(e.keyCode==32){
							var node=ui.window.querySelector('pausedbg');
							if(node){
								node.click();
							}
							else{
								ui.click.pause();
							}
						}
						else if(e.keyCode==65){
							if(ui.auto) ui.auto.click();
						}
						else if(e.keyCode==87){
							if(ui.wuxie&&ui.wuxie.style.display!='none'){
								ui.wuxie.classList.toggle('glow')
							}
							else if(ui.tempnowuxie){
								ui.tempnowuxie.classList.toggle('glow')
							}
						}
						else 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)){
							e.preventDefault();
							e.stopPropagation();
							return false;
						}
						else if(e.keyCode==74&&(e.ctrlKey||e.metaKey)&&lib.node){
							lib.node.debug();
						}
						// else if(e.keyCode==27){
						// 	if(!ui.arena.classList.contains('paused')) ui.click.config();
						// }
					}
				};
				window.onload=function(){
					if(lib.device){
						var script=document.createElement('script');
						script.src='cordova.js';
						document.body.appendChild(script);
						document.addEventListener('deviceready',function(){
							if(lib.init.cordovaReady){
								lib.init.cordovaReady();
								delete lib.init.cordovaReady;
							}
						});
					}
					if(_status.packLoaded){
						delete _status.packLoaded;
						lib.init.onload();
					}
					else{
						_status.windowLoaded=true;
					}
				};

				window.onerror=function(msg,src,line,column,err){
					const winPath=window.__dirname?('file:///'+(__dirname.replace(new RegExp('\\\\','g'),'/')+'/')):'';
					let str=`错误文件: ${typeof src=='string'?decodeURI(src).replace(lib.assetURL,'').replace(winPath,''):'未知文件'}`;
					str+=`\n错误信息: ${msg}`;
					const tip=lib.getErrorTip(msg);
					if(tip) str+=`\n错误提示: ${tip}`;
					str+=`\n行号: ${line}`;
					str+=`\n列号: ${column}`;
					const version=lib.version||'';
					const reg=/[^\d\.]/;
					const match=version.match(reg)!=null;
					str+='\n'+`${match?'游戏':'无名杀'}版本: ${version||'未知版本'}`;
					if(match) str+='\n⚠️您使用的游戏代码不是源于libccy/noname无名杀官方仓库,请自行寻找您所使用的游戏版本开发者反馈!';
					if(_status&&_status.event){
						let evt=_status.event;
						str+=`\nevent.name: ${evt.name}\nevent.step: ${evt.step}`;
						if(evt.parent) str+=`\nevent.parent.name: ${evt.parent.name}\nevent.parent.step: ${evt.parent.step}`;
						if(evt.parent&&evt.parent.parent) str+=`\nevent.parent.parent.name: ${evt.parent.parent.name}\nevent.parent.parent.step: ${evt.parent.parent.step}`;
						if(evt.player||evt.target||evt.source||evt.skill||evt.card){
							str+='\n-------------'
						}
						if(evt.player){
							if(lib.translate[evt.player.name]) str+=`\nplayer: ${lib.translate[evt.player.name]}[${evt.player.name}]`;
							else str+='\nplayer: '+evt.player.name;
							let distance=get.distance(_status.roundStart,evt.player,'absolute');
							if (distance!=Infinity) {
								str+=`\n座位号: ${distance+1}`;
							}
						}
						if(evt.target){
							if(lib.translate[evt.target.name]) str+=`\ntarget: ${lib.translate[evt.target.name]}[${evt.target.name}]`;
							else str+='\ntarget: '+evt.target.name;
						}
						if(evt.source){
							if(lib.translate[evt.source.name]) str+=`\nsource: ${lib.translate[evt.source.name]}[${evt.source.name}]`;
							else str+='\nsource: '+evt.source.name;
						}
						if(evt.skill){
							if(lib.translate[evt.skill]) str+=`\nskill: ${lib.translate[evt.skill]}[${evt.skill}]`;
							else str+='\nskill: '+evt.skill;
						}
						if(evt.card){
							if(lib.translate[evt.card.name]) str+=`\ncard: ${lib.translate[evt.card.name]}[${evt.card.name}]`;
							else str+='\ncard: '+evt.card.name;
						}
					}
					str+='\n-------------';
					if(typeof line=='number'&&(typeof game.readFile=='function'||location.origin!='file://')){
						function createShowCode(lines){
							let showCode='';
							if(lines.length>=10){ 
								if(line>4){ 
									for(let i=line-5;i<line+6&&i<lines.length;i++){ 
										showCode+=`${i+1}| ${line==i+1?'⚠️':''}${lines[i]}\n`;
									} 
								}else{ 
									for(let i=0;i<line+6&&i<lines.length;i++){ 
										showCode+=`${i+1}| ${line==i+1?'⚠️':''}${lines[i]}\n`;
									} 
								} 
							}else{ 
								showCode=lines.map((_line,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=navigator.userAgent.toLowerCase();
					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')){
					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<lib.config.customBackgroundPack.length;i++){
							var link=lib.config.customBackgroundPack[i];
							lib.configMenu.appearence.config.image_background.item[link]=link.slice(link.indexOf('_')+1);
						}
						lib.configMenu.appearence.config.image_background.item.default='默认';
					}
					if(pack.music){
						if(lib.device||typeof window.require=='function'){
							lib.configMenu.audio.config.background_music.item.music_custom='自定义音乐';
						}
						lib.config.all.background_music=['music_default'];
						for(i in pack.music){
							lib.config.all.background_music.push(i);
							lib.configMenu.audio.config.background_music.item[i]=pack.music[i];
						}
						if(lib.config.customBackgroundMusic){
							for(i in lib.config.customBackgroundMusic){
								lib.config.all.background_music.push(i);
								lib.configMenu.audio.config.background_music.item[i]=lib.config.customBackgroundMusic[i];
							}
						}
						lib.configMenu.audio.config.background_music.item.music_random='随机播放';
						lib.configMenu.audio.config.background_music.item.music_off='关闭';
					}
					if(pack.theme){
						for(i in pack.theme){
							lib.configMenu.appearence.config.theme.item[i]=pack.theme[i];
						}
					}
					if(lib.config.extension_sources){
						for(i in lib.config.extension_sources){
							lib.configMenu.general.config.extension_source.item[i]=i;
						}
					}

					if(pack.font){
						ui.css.fontsheet=lib.init.sheet();
						const appearenceConfig=lib.configMenu.appearence.config,fontSheet=ui.css.fontsheet.sheet,suitsFont=lib.config.suits_font;
						Object.keys(pack.font).forEach(value=>{
							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=navigator.userAgent.toLowerCase();
					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<lib.config.extensions.length;i++){
									game.saveConfig('extension_'+lib.config.extensions[i]+'_enable',false);
								}
								localStorage.setItem(lib.configprefix+'disable_extension',true);
							}
						}
						for(var i=0;i<lib.config.plays.length;i++){
							if(lib.config.all.plays.includes(lib.config.plays[i])){
								extensionlist.push(lib.config.plays[i]);
							}
						}
						var alerted=false;
						for(var i=0;i<lib.config.extensions.length;i++){
							if(window.bannedExtensions.contains(lib.config.extensions[i])){
								//if(!alerted) alert('读取某些扩展时出现问题。');
								alerted=true;
								continue;
							}
							var extcontent=localStorage.getItem(lib.configprefix+'extension_'+lib.config.extensions[i]);
							if(extcontent){
								//var backup_onload=lib.init.onload;
								_status.evaluatingExtension=true;
								try{
									eval(extcontent);
								}
								catch(e){
									console.log(e);
								}
								//lib.init.onload=backup_onload;
								_status.evaluatingExtension=false;
							}
							else if(lib.config.mode!='connect'||(!localStorage.getItem(lib.configprefix+'directstart')&&show_splash)){
								extensionlist.push(lib.config.extensions[i]);
							}
						}
					}
					else{
						if(lib.config.mode!='connect'||(!localStorage.getItem(lib.configprefix+'directstart')&&show_splash)){
							var alerted=false;
							for(var i=0;i<lib.config.extensions.length;i++){
								if(window.bannedExtensions.contains(lib.config.extensions[i])){
									//if(!alerted) alert('读取某些扩展时出现问题。');
									alerted=true;
									continue;
								}
								game.import('extension',{name:lib.config.extensions[i]});
							}
						}
					}
					const loadPack=()=>{
						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;
					game.dynamicStyle.init();
					lib.announce.init();
					// node:path library alternative
					if (typeof module!="object"||typeof module.exports!="object") lib.init.js(`${lib.assetURL}game`,"path",()=>{
						lib.path=window._noname_path;
						delete window._noname_path;
					},e=>{
						console.log(e);
					});
					var styleToLoad=6;
					var styleLoaded=gnc.of(function*(){
						--styleToLoad;
						if(styleToLoad==0){
							if(extensionlist.length&&(lib.config.mode!='connect'||show_splash)){
								_status.extensionLoading=[];
								let extToLoad=extensionlist.length;
								const extLoaded=gnc.of(function*(){
									--extToLoad;
									if(extToLoad==0){
										yield Promise.allSettled(_status.extensionLoading);
										delete _status.extensionLoading;
										loadPack();
									}
								});
								//读取扩展
								var alerted=false;
								for(var i=0;i<extensionlist.length;i++){
									if(window.bannedExtensions.contains(extensionlist[i])){
										alerted=true;
										--extToLoad;
										if(extToLoad==0){
											yield Promise.allSettled(_status.extensionLoading);
											delete _status.extensionLoading;
											loadPack();
										}
										continue;
									}
									lib.init.js(lib.assetURL+'extension/'+extensionlist[i],'extension',extLoaded,(function(i){
										return gnc.of(function*(){
											game.removeExtension(i);
											--extToLoad;
											if(extToLoad==0){
												yield Promise.allSettled(_status.extensionLoading);
												delete _status.extensionLoading;
												loadPack();
											}
										});
									}(extensionlist[i])));
								}
							}
							else{
								loadPack();
							}
						}
					});
					if(lib.config.layout=='default'){
						lib.config.layout='mobile';
					}
					ui.css.layout=lib.init.css(lib.assetURL+'layout/'+layout,'layout',styleLoaded);
					if(get.is.phoneLayout()){
						ui.css.phone=lib.init.css(lib.assetURL+'layout/default','phone',styleLoaded);
					}
					else{
						ui.css.phone=lib.init.css();
						styleToLoad--;
					}
					ui.css.theme=lib.init.css(lib.assetURL+'theme/'+lib.config.theme,'style',styleLoaded);
					ui.css.card_style=lib.init.css(lib.assetURL+'theme/style/card',lib.config.card_style,styleLoaded);
					ui.css.cardback_style=lib.init.css(lib.assetURL+'theme/style/cardback',lib.config.cardback_style,styleLoaded);
					ui.css.hp_style=lib.init.css(lib.assetURL+'theme/style/hp',lib.config.hp_style,styleLoaded);

					if(lib.config.player_style&&lib.config.player_style!='default'&&lib.config.player_style!='custom'){
						var str='';
						switch(lib.config.player_style){
							case 'wood':str='url("'+lib.assetURL+'theme/woodden/wood.jpg")';break;
							case 'music':str='linear-gradient(#4b4b4b, #464646)';break;
							case 'simple':str='linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))';break;
						}
						ui.css.player_stylesheet=lib.init.sheet('#window .player{background-image:'+str+'}');
					}
					if(lib.config.border_style&&lib.config.border_style!='default'&&lib.config.border_style!='custom'&&lib.config.border_style!='auto'){
						ui.css.border_stylesheet=lib.init.sheet();
						var bstyle=lib.config.border_style;
						if(bstyle.startsWith('dragon_')){
							bstyle=bstyle.slice(7);
						}
						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/'+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<entries.length;i++){
												if(entries[i].isDirectory){
													folders.push(entries[i].name);
												}
												else{
													files.push(entries[i].name);
												}
											}
											success(folders,files);
										}
										else{
											entries=entries.concat(Array.from(results));
											readEntries();
										}
									},failure);
								};
								readEntries();
							},failure);
						};
						game.ensureDirectory=(list,callback,file)=>{
							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<filelist.length;i++){
									if(filelist[i][0]!='.'&&filelist[i][0]!='_'){
										if(lib.node.fs.statSync(dir+'/'+filelist[i]).isDirectory()){
											folders.push(filelist[i]);
										}
										else{
											files.push(filelist[i]);
										}
									}
								}
								success(folders,files);
							});
						}
						catch(e){
							failure(e);
						}
					};
					game.ensureDirectory=(list,callback,file)=>{
						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<character[i][j][k][3].length;l++){
										lib.skilllist.add(character[i][j][k][3][l]);
									}
								}
								if(j=='skill'&&k[0]=='_'&&(lib.config.mode!='connect'?(!lib.config.characters.contains(i)):(!character[i].connect))){
									continue;
								}
								if(j=='translate'&&k==i){
									lib[j][k+'_character_config']=character[i][j][k];
								}
								else{
									if(lib[j][k]==undefined){
										if(j=='skill'&&!character[i][j][k].forceLoad&&lib.config.mode=='connect'&&!character[i].connect){
											lib[j][k]={
												nopop:character[i][j][k].nopop,
												derivation:character[i][j][k].derivation
											};
										}
										else{
											Object.defineProperty(lib[j],k,Object.getOwnPropertyDescriptor(character[i][j],k));
										}
										if(j=='card'&&lib[j][k].derivation){
											if(!lib.cardPack.mode_derivation){
												lib.cardPack.mode_derivation=[k];
											}
											else{
												lib.cardPack.mode_derivation.push(k);
											}
										}
									}
									else if(Array.isArray(lib[j][k])&&Array.isArray(character[i][j][k])){
										lib[j][k].addArray(character[i][j][k]);
									}
									else{
										console.log(
											`dublicate ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`,
											lib[j][k],
											`\ncharacter.${i}.${j}.${k}`,
											character[i][j][k]
										);
									}
								}
							}
						}
					}
					var connect_avatar_list=[];
					for(var i in lib.character){
						connect_avatar_list.push(i);
					}
					connect_avatar_list.sort(lib.sort.capt);
					for(var i=0;i<connect_avatar_list.length;i++){
						var ia=connect_avatar_list[i];
						lib.mode.connect.config.connect_avatar.item[ia]=lib.translate[ia];
					}
					if(lib.config.mode!='connect'){
						var pilecfg=lib.config.customcardpile[get.config('cardpilename')||'当前牌堆'];
						if(pilecfg){
							lib.config.bannedpile=get.copy(pilecfg[0]||{});
							lib.config.addedpile=get.copy(pilecfg[1]||{});
						}
						else{
							lib.config.bannedpile={};
							lib.config.addedpile={};
						}
					}
					else{
						lib.cardPackList={};
					}
					for(i in card){
						const cardPack=lib.cardPack[i]?lib.cardPack[i]:lib.cardPack[i]=[];
						if(card[i].card){
							for(var j in card[i].card){
								if(!card[i].card[j].hidden&&card[i].translate[j+'_info']){
									cardPack.push(j);
								}
							}
						}
						for(j in card[i]){
							if(j=='mode'||j=='forbid') continue;
							if(j=='connect'){
								connectCardPack.push(i);
								continue;
							}
							if(j=='list'){
								if(lib.config.mode=='connect'){
									const cardPackList=lib.cardPackList[i];
									if(cardPackList) cardPackList.addArray(card[i][j]);
									else lib.cardPackList[i]=card[i][j];
								}
								else{
									if(lib.config.cards.contains(i)){
										var pile;
										if(typeof card[i][j]=='function'){
											pile=card[i][j]();
										}
										else{
											pile=card[i][j];
										}
										const cardPile=lib.cardPile[i];
										if(cardPile) cardPile.addArray(pile);
										else lib.cardPile[i]=pile.slice(0);
										if(lib.config.bannedpile[i]){
											for(var k=0;k<lib.config.bannedpile[i].length;k++){
												pile[lib.config.bannedpile[i][k]]=null;
											}
										}
										for(var k=0;k<pile.length;k++){
											if(!pile[k]){
												pile.splice(k--,1);
											}
										}
										if(lib.config.addedpile[i]){
											for(var k=0;k<lib.config.addedpile[i].length;k++){
												pile.push(lib.config.addedpile[i][k]);
											}
										}
										lib.card.list.addArray(pile);
									}
								}
							}
							else{
								for(k in card[i][j]){
									if(j=='skill'&&k[0]=='_'&&!card[i][j][k].forceLoad&&(lib.config.mode!='connect'?(!lib.config.cards.contains(i)):(!card[i].connect))){
										continue;
									}
									if(j=='translate'&&k==i){
										lib[j][k+'_card_config']=card[i][j][k];
									}
									else{
										if(lib[j][k]==undefined){
											if(j=='skill'&&!card[i][j][k].forceLoad&&lib.config.mode=='connect'&&!card[i].connect){
												lib[j][k]={
													nopop:card[i][j][k].nopop,
													derivation:card[i][j][k].derivation
												};
											}
											else{
												Object.defineProperty(lib[j],k,Object.getOwnPropertyDescriptor(card[i][j],k));
											}
										}
										else{
											console.log(
												`dublicate ${j} in card ${i}:\n${k}:\nlib.${j}.${k}`,
												lib[j][k],
												`\ncard.${i}.${j}.${k}`,
												card[i][j][k]
											);
										}
										if(j=='card'&&lib[j][k].derivation){
											if(!lib.cardPack.mode_derivation){
												lib.cardPack.mode_derivation=[k];
											}
											else{
												lib.cardPack.mode_derivation.push(k);
											}
										}
									}
								}
							}
						}
					}
					if(lib.cardPack.mode_derivation){
						for(var i=0;i<lib.cardPack.mode_derivation.length;i++){
							if(typeof lib.card[lib.cardPack.mode_derivation[i]].derivation=='string'&&!lib.character[lib.card[lib.cardPack.mode_derivation[i]].derivation]){
								lib.cardPack.mode_derivation.splice(i--,1);
							}
							else if(typeof lib.card[lib.cardPack.mode_derivation[i]].derivationpack=='string'&&!lib.config.cards.contains(lib.card[lib.cardPack.mode_derivation[i]].derivationpack)){
								lib.cardPack.mode_derivation.splice(i--,1);
							}
						}
						if(lib.cardPack.mode_derivation.length==0){
							delete lib.cardPack.mode_derivation;
						}
					}
					if(lib.config.mode!='connect'){
						for(i in play){
							if(lib.config.hiddenPlayPack.contains(i)) continue;
							if(play[i].forbid&&play[i].forbid.contains(lib.config.mode)) continue;
							if(play[i].mode&&play[i].mode.contains(lib.config.mode)==false) continue;
							for(j in play[i].element){
								if(!lib.element[j]) lib.element[j]=[];
								for(k in play[i].element[j]){
									if(k=='init'){
										if(!lib.element[j].inits) lib.element[j].inits=[];
										lib.element[j].inits.push(play[i].element[j][k]);
									}
									else{
										lib.element[j][k]=play[i].element[j][k];
									}
								}
							}
							for(j in play[i].ui){
								if(typeof play[i].ui[j]=='object'){
									if(ui[j]==undefined) ui[j]={};
									for(k in play[i].ui[j]){
										ui[j][k]=play[i].ui[j][k];
									}
								}
								else{
									ui[j]=play[i].ui[j];
								}
							}
							for(j in play[i].game){
								game[j]=play[i].game[j];
							}
							for(j in play[i].get){
								get[j]=play[i].get[j];
							}
							for(j in play[i]){
								if(j=='mode'||j=='forbid'||j=='init'||j=='element'||
								j=='game'||j=='get'||j=='ui'||j=='arenaReady') continue;
								for(k in play[i][j]){
									if(j=='translate'&&k==i){
										// lib[j][k+'_play_config']=play[i][j][k];
									}
									else{
										if(lib[j][k]!=undefined){
											console.log(
												`dublicate ${j} in play ${i}:\n${k}:\nlib.${j}.${k}`,
												lib[j][k],
												`\nplay.${i}.${j}.${k}`,
												play[i][j][k]
											);
										}
										lib[j][k]=play[i][j][k];
									}
								}
							}
							if(typeof play[i].init=='function') play[i].init();
							if(typeof play[i].arenaReady=='function') lib.arenaReady.push(play[i].arenaReady);
						}
					}

					lib.connectCharacterPack=[];
					lib.connectCardPack=[];
					for(var i=0;i<lib.config.all.characters.length;i++){
						var packname=lib.config.all.characters[i];
						if(connectCharacterPack.contains(packname)){
							lib.connectCharacterPack.push(packname)
						}
					}
					for(var i=0;i<lib.config.all.cards.length;i++){
						var packname=lib.config.all.cards[i];
						if(connectCardPack.contains(packname)){
							lib.connectCardPack.push(packname)
						}
					}
					if(lib.config.mode!='connect'){
						for(i=0;i<lib.card.list.length;i++){
							if(lib.card.list[i][2]=='huosha'){
								lib.card.list[i]=lib.card.list[i].slice(0);
								lib.card.list[i][2]='sha';
								lib.card.list[i][3]='fire';
							}
							else if(lib.card.list[i][2]=='leisha'){
								lib.card.list[i]=lib.card.list[i].slice(0);
								lib.card.list[i][2]='sha';
								lib.card.list[i][3]='thunder';
							}
							if(!lib.card[lib.card.list[i][2]]){
								lib.card.list.splice(i,1);i--;
							}
							else if(lib.card[lib.card.list[i][2]].mode&&
								lib.card[lib.card.list[i][2]].mode.contains(lib.config.mode)==false){
								lib.card.list.splice(i,1);i--;
							}
						}
					}

					if(lib.config.mode=='connect'){
						_status.connectMode=true;
					}
					if(window.isNonameServer){
						lib.cheat.i();
					}
					else if(lib.config.dev&&(!_status.connectMode||lib.config.debug)){
						lib.cheat.i();
					}
					lib.config.sort_card=get.sortCard(lib.config.sort);
					delete lib.imported.character;
					delete lib.imported.card;
					delete lib.imported.mode;
					delete lib.imported.play;
					for(var i in lib.init){
						if(i.startsWith('setMode_')){
							delete lib.init[i];
						}
					}
					if(!_status.connectMode){
						for(var i=0;i<lib.extensions.length;i++){
							try{
								_status.extension=lib.extensions[i][0];
								_status.evaluatingExtension=lib.extensions[i][3];
								if (typeof lib.extensions[i][1]=="function") 
									yield (gnc.is.coroutine(lib.extensions[i][1])?gnc.of(lib.extensions[i][1]):lib.extensions[i][1]).call(lib.extensions[i],lib.extensions[i][2],lib.extensions[i][4]);
								if(lib.extensions[i][4]){
									if(lib.extensions[i][4].character){
										for(var j in lib.extensions[i][4].character.character){
											game.addCharacterPack(get.copy(lib.extensions[i][4].character));
											break;
										}
									}
									if(lib.extensions[i][4].card){
										for(var j in lib.extensions[i][4].card.card){
											game.addCardPack(get.copy(lib.extensions[i][4].card));
											break;
										}
									}
									if(lib.extensions[i][4].skill){
										for(var j in lib.extensions[i][4].skill.skill){
											game.addSkill(j,lib.extensions[i][4].skill.skill[j],
											lib.extensions[i][4].skill.translate[j],
											lib.extensions[i][4].skill.translate[j+'_info'],
											lib.extensions[i][4].skill.translate[j+'_append']);
										}
									}
								}
								delete _status.extension;
								delete _status.evaluatingExtension;
							}
							catch(e){
								console.log(e);
							}
						}
					}
					delete lib.extensions;

					if(lib.init.startBefore){
						lib.init.startBefore();
						delete lib.init.startBefore;
					}
					ui.create.arena();
					game.createEvent('game',false).setContent(lib.init.start);
					if(lib.mode[lib.config.mode]&&lib.mode[lib.config.mode].fromextension){
						var startstr=mode[lib.config.mode].start.toString();
						if(startstr.indexOf('onfree')==-1){
							setTimeout(lib.init.onfree,500);
						}
					}
					delete lib.init.start;
					if(Array.isArray(_status.onprepare)&&_status.onprepare.length){
						yield Promise.allSettled(_status.onprepare);
						delete _status.onprepare;
					}
					game.loop();
				})
				var proceed=gnc.of(function*(){
					if(!lib.db){
						try{
							lib.storage=JSON.parse(localStorage.getItem(lib.configprefix+lib.config.mode));
							if(typeof lib.storage!='object') throw('err');
							if(lib.storage==null) throw('err');
						}
						catch(err){
							lib.storage={};
							localStorage.setItem(lib.configprefix+lib.config.mode,"{}");
						}
						yield proceed2();
					}
					else{
						game.getDB('data',lib.config.mode,function(obj){
							lib.storage=obj||{};
							proceed2();
						});
					}
				});
				if(!lib.imported.mode||!lib.imported.mode[lib.config.mode]){
					window.inSplash=true;
					clearTimeout(window.resetGameTimeout);
					delete window.resetGameTimeout;
					var clickedNode=false;
					var clickNode=function(){
						if(clickedNode) return;
						this.classList.add('clicked');
						clickedNode=true;
						lib.config.mode=this.link;
						game.saveConfig('mode',this.link);
						if(this.link=='connect'){
							localStorage.setItem(lib.configprefix+'directstart',true);
							game.reload();
						}
						else{
							if(game.layout!='mobile'&&lib.layoutfixed.indexOf(lib.config.mode)!==-1){
								game.layout='mobile';
								ui.css.layout.href=lib.assetURL+'layout/'+game.layout+'/layout.css';
							}
							else if(game.layout=='mobile'&&lib.config.layout!='mobile'&&lib.layoutfixed.indexOf(lib.config.mode)===-1){
								game.layout=lib.config.layout;
								if(game.layout=='default'){
									ui.css.layout.href='';
								}
								else{
									ui.css.layout.href=lib.assetURL+'layout/'+game.layout+'/layout.css';
								}
							}
							splash.delete(1000);
							delete window.inSplash;
							window.resetGameTimeout=setTimeout(lib.init.reset,10000);
	
							this.listenTransition(function(){
								lib.init.js(lib.assetURL+'mode',lib.config.mode,proceed);
							},500);
						}
					}
					var downNode=function(){
						this.classList.add('glow');
					}
					var upNode=function(){
						this.classList.remove('glow');
					}
					var splash=ui.create.div('#splash',document.body);
					if(lib.config.touchscreen){
						splash.classList.add('touch');
						lib.setScroll(splash);
					}
					if(lib.config.player_border!='wide'){
						splash.classList.add('slim');
					}
					splash.dataset.radius_size=lib.config.radius_size;
					for(var i=0;i<lib.config.all.mode.length;i++){
						var node=ui.create.div('.hidden',splash,clickNode);
						node.link=lib.config.all.mode[i];
						ui.create.div(node,'.splashtext',get.verticalStr(get.translation(lib.config.all.mode[i])));
						if(lib.config.all.stockmode.includes(lib.config.all.mode[i])){
							// 初始启动页设置
							if(lib.config.splash_style==undefined) game.saveConfig('splash_style','style1');
							splash.dataset.splash_style=lib.config.splash_style;
							// 扩展可通过window.splashurl设置素材读取路径
							if(window.splashurl==undefined)window.splashurl='image/splash/';
							if(lib.config.splash_style=='style1'||lib.config.splash_style=='style2'){
								ui.create.div(node,'.avatar').setBackgroundImage('image/splash/'+lib.config.splash_style+'/'+lib.config.all.mode[i]+'.jpg');
							}else{
								ui.create.div(node,'.avatar').setBackgroundImage(splashurl+lib.config.splash_style+'/'+lib.config.all.mode[i]+'.jpg');
							}
						}
						else{
							var avatarnode=ui.create.div(node,'.avatar');
							var avatarbg=lib.mode[lib.config.all.mode[i]].splash;
							if(avatarbg.startsWith('ext:')){
								avatarnode.setBackgroundImage(avatarbg.replace(/^ext:/,'extension/'));
							}
							else{
								avatarnode.setBackgroundDB(avatarbg);
							}
						}
						if(!lib.config.touchscreen){
							node.addEventListener('mousedown',downNode);
							node.addEventListener('mouseup',upNode);
							node.addEventListener('mouseleave',upNode);
						}
						setTimeout((function(node){
							return function(){
								node.show();
							}
						}(node)),i*100);
					}
					if(lib.config.mousewheel){
						splash.onmousewheel=ui.click.mousewheel;
					}
				}
				else{
					yield proceed();
				}
				localStorage.removeItem(lib.configprefix+'directstart');
				delete lib.init.init;
				const libOnload2=lib.onload2;
				delete lib.onload2;
				while(Array.isArray(libOnload2)&&libOnload2.length){
					const fun=libOnload2.shift();
					if(typeof fun!="function") continue;
					yield (gnc.is.generatorFunc(fun)?gnc.of(fun):fun)();
				}
			}),
			startOnline:function(){
				'step 0'
				event._resultid=null;
				event._result=null;
				game.pause();
				'step 1'
				if(result){
					if(event._resultid){
						result.id=event._resultid;
					}
					game.send('result',result);
				}
				event.goto(0);
			},
			onfree:function(){
				if(lib.onfree){
					clearTimeout(window.resetGameTimeout);
					delete window.resetGameTimeout;
					if(!game.syncMenu){
						delete window.resetExtension;
						localStorage.removeItem(lib.configprefix+'disable_extension');
					}

					if(game.removeFile&&lib.config.brokenFile.length){
						while(lib.config.brokenFile.length){
							game.removeFile(lib.config.brokenFile.shift());
						}
						game.saveConfigValue('brokenFile');
					}

					var onfree=lib.onfree;
					delete lib.onfree;
					var loop=function(){
						if(onfree.length){
							(onfree.shift())();
							setTimeout(loop,100);
						}
					};
					setTimeout(loop,500);
					if(!_status.new_tutorial) game.saveConfig('menu_loadondemand',true,lib.config.mode);
				}
			},
			connection:function(ws){
				var client={
					ws:ws,
					id:ws.wsid||get.id(),
					closed:false
				};
				lib.node.clients.push(client);
				for(var i in lib.element.client){
					client[i]=lib.element.client[i];
				}
				if(window.isNonameServer){
					document.querySelector('#server_count').innerHTML=lib.node.clients.length;
				}
				ws.on('message',function(messagestr){
					var message;
					try{
						message=JSON.parse(messagestr);
						if(!Array.isArray(message)||
							typeof lib.message.server[message[0]]!=='function'){
							throw('err');
						}
						for(var i=1;i<message.length;i++){
							message[i]=get.parsedResult(message[i]);
						}
					}
					catch(e){
						console.log(e);
						console.log('invalid message: '+messagestr);
						return;
					}
					lib.message.server[message.shift()].apply(client,message);
				});
				ws.on('close',function(){
					client.close();
				});
				client.send('opened');
			},
			sheet:function(){
				var style=document.createElement('style');
				document.head.appendChild(style);
				for(var i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='string'){
						style.sheet.insertRule(arguments[i],0);
					}
				}
				return style;
			},
			css:(path,file,before)=>{
				const style=document.createElement("link");
				style.rel="stylesheet";
				if(path){
					if(path[path.length-1]=='/') path=path.slice(0,path.length-1);
					if(file) path=`${path}${/^db:extension-[^:]*$/.test(path)?':':'/'}${file}.css`;
					(path.startsWith('db:')?game.getDB('image',path.slice(3)).then(get.objectURL):new Promise(resolve=>resolve(path))).then(resolvedPath=>{
						style.href=resolvedPath;
						if(typeof before=='function'){
							style.addEventListener('load',before);
							document.head.appendChild(style);
						}
						else if(before) document.head.insertBefore(style,before);
						else document.head.appendChild(style);
					});
				}
				return style;
			},
			//在扩展的precontent中调用,用于加载扩展必需的JS文件。
			//If any of the parameters is an Array, corresponding files will be loaded in order
			//如果任意参数为数组,则按顺序加载加载相应的文件
			jsForExtension:(path,file,onLoad,onError)=>{
				if(!_status.javaScriptExtensions) _status.javaScriptExtensions=[];
				_status.javaScriptExtensions.push({
					path:path,
					file:file,
					onLoad:onLoad,
					onError:onError
				});
			},
			js:(path,file,onLoad,onError)=>{
				if(path[path.length-1]=='/') path=path.slice(0,path.length-1);
				if(path==`${lib.assetURL}mode`&&lib.config.all.stockmode.indexOf(file)==-1){
					lib.genAwait(lib.init[`setMode_${file}`]()).then(onLoad);
					return;
				}
				if(Array.isArray(file)){
					file.forEach(value=>lib.init.js(path,value,onLoad,onError));
					return;
				}
				let scriptSource=file?`${path}${/^db:extension-[^:]*$/.test(path)?':':'/'}${file}.js`:path;
				if(path.startsWith('http')) scriptSource+=`?rand=${get.id()}`;
				else if(lib.config.fuck_sojson&&scriptSource.includes('extension')!=-1&&scriptSource.startsWith(lib.assetURL)){
					const pathToRead=scriptSource.slice(lib.assetURL.length);
					const alertMessage=`检测到您安装了使用免费版sojson进行加密的扩展。请谨慎使用这些扩展,避免游戏数据遭到破坏。\n扩展文件:${pathToRead}`;
					if(typeof game.readFileAsText=='function') game.readFileAsText(pathToRead,result=>{
						if(result.includes('sojson')||result.includes('jsjiami')||result.includes('var _0x')) alert(alertMessage);
					},()=>void 0);
					else if(location.origin!='file://') lib.init.reqSync(pathToRead,function(){
						const result = this.responseText;
						if(result.includes('sojson')||result.includes('jsjiami')||result.includes('var _0x')) alert(alertMessage);
					},()=>void 0);
				}
				const script=document.createElement('script');
				(scriptSource.startsWith('db:')?game.getDB('image',scriptSource.slice(3)).then(get.objectURL):new Promise(resolve=>resolve(scriptSource))).then(resolvedScriptSource=>{
					script.src=resolvedScriptSource;
					if(path.startsWith('http')) script.addEventListener('load',()=>script.remove());
					document.head.appendChild(script);
					if(typeof onLoad=='function') script.addEventListener('load',onLoad);
					if(typeof onError=='function') script.addEventListener('error',onError);
				});
				return script;
			},
			/**
			 * 同步lib.init.js
			 * @returns { void }
			 */
			jsSync:(path,file,onLoad,onError)=>{
				if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){
					const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api');
					if(typeof onError=='function') onError(e);
					else throw e;
					return;
				}
				if(path[path.length-1]=='/') path=path.slice(0,path.length-1);
				if(path==`${lib.assetURL}mode`&&lib.config.all.stockmode.indexOf(file)==-1){
					lib.genAwait(lib.init[`setMode_${file}`]()).then(onLoad);
					return;
				}
				if(Array.isArray(file)){
					return file.forEach(value=>lib.init.js(path,value,onLoad,onError));
				}
				let scriptSource;
				if(!file) scriptSource=path;
				else scriptSource=`${path}/${file}.js`;
				if(path.startsWith('http')) scriptSource+=`?rand=${get.id()}`;
				const xmlHttpRequest=new XMLHttpRequest();
				let data;
				xmlHttpRequest.addEventListener("load",()=>{
					data=xmlHttpRequest.responseText;
					if(!data) {
						if(typeof onError=='function') onError(new Error(`${scriptSource}加载失败!`));
						return;
					}
					if(lib.config.fuck_sojson&&scriptSource.includes('extension')!=-1&&scriptSource.startsWith(lib.assetURL)){
						const pathToRead=scriptSource.slice(lib.assetURL.length);
						if(data.includes('sojson')||data.includes('jsjiami')||data.includes('var _0x')) alert(`检测到您安装了使用免费版sojson进行加密的扩展。请谨慎使用这些扩展,避免游戏数据遭到破坏。\n扩展文件:${pathToRead}`);
					}
					try{
						window.eval(data);
						if(typeof onLoad=='function') onLoad();
					}
					catch(error){
						if(typeof onError=='function') onError(error);
					}
				});
				if(typeof onError=='function') xmlHttpRequest.addEventListener("error",onError);
				xmlHttpRequest.open("GET",scriptSource,false);
				xmlHttpRequest.send();
			},
			req:(str,onload,onerror,master)=>{
				let sScriptURL;
				if(str.startsWith('http')) sScriptURL=str;
				else if(str.startsWith('local:')){
					if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){
						const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api');
						if(typeof onerror=='function') onerror(e);
						else throw e;
						return;
					}
					sScriptURL=lib.assetURL+str.slice(6);
				}
				else{
					let url=get.url(master);
					if(url[url.length-1]!='/') url+='/';
					sScriptURL=url+str;
				}
				const oReq=new XMLHttpRequest();
				if(typeof onload=='function') oReq.addEventListener("load",onload);
				if(typeof onerror=='function') oReq.addEventListener("error",onerror);
				oReq.open("GET",sScriptURL);
				oReq.send();
			},
			/**
			 * 同步lib.init.req
			 */
			reqSync:(str,onload,onerror,master)=>{
				let sScriptURL;
				if(str.startsWith('http')) sScriptURL=str;
				else if(str.startsWith('local:')){
					if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){
						const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api');
						if(typeof onerror=='function') onerror(e);
						else throw e;
						return;
					}
					sScriptURL=lib.assetURL+str.slice(6);
				}
				else{
					let url=get.url(master);
					if(url[url.length-1]!='/')url+='/';
					sScriptURL=url+str;
				}
				const oReq=new XMLHttpRequest();
				if(typeof onload=='function') oReq.addEventListener("load",onload);
				if(typeof onerror=='function') oReq.addEventListener("error",onerror);
				oReq.open("GET",sScriptURL,false);
				oReq.send();
				if(typeof onload!=='function') return oReq.responseText;
			},
			json:(url,onload,onerror)=>{
				const oReq=new XMLHttpRequest();
				if(typeof onload=='function') oReq.addEventListener("load",()=>{
					let result;
					try{
						result=JSON.parse(oReq.responseText);
						if(!result) throw('err');
					}
					catch(e){
						if(typeof onerror=='function') onerror(e);
						return;
					}
					onload(result);
				});
				if(typeof onerror=='function') oReq.addEventListener("error",onerror);
				oReq.open("GET",url);
				oReq.send();
			},
			/**
			 * 同步lib.init.json
			 */
			jsonSync:(url,onload,onerror)=>{
				if(lib.assetURL.length==0&&location.origin=='file://'&&typeof game.readFile=='undefined'){
					const e=new Error('浏览器file协议下无法使用此api,请在http/https协议下使用此api');
					if(typeof onerror=='function') onerror(e);
					else throw e;
					return;
				}
				const oReq=new XMLHttpRequest();
				if(typeof onload=='function') oReq.addEventListener("load",()=>{
					let result;
					try{
						result=JSON.parse(oReq.responseText);
						if(!result) throw('err');
					}
					catch(e){
						if(typeof onerror=='function') onerror(e);
						return;
					}
					onload(result);
				});
				if(typeof onerror=='function') oReq.addEventListener("error",onerror);
				oReq.open("GET",url,false);
				oReq.send();
			},
			cssstyles:function(){
				if(ui.css.styles){
					ui.css.styles.remove();
				}
				ui.css.styles=lib.init.sheet();
				ui.css.styles.sheet.insertRule('#arena .player>.name,#arena .button.character>.name {font-family: '+(lib.config.name_font||'xinwei')+',xinwei}',0);
				ui.css.styles.sheet.insertRule('#arena .player>.name,.button.character>.name {font-family: '+(lib.config.name_font||'xinwei')+',xinwei}',0);
				ui.css.styles.sheet.insertRule('#arena .player .identity>div {font-family: '+(lib.config.identity_font||'huangcao')+',xinwei}',0);
				ui.css.styles.sheet.insertRule('.button.character.newstyle>.identity {font-family: '+(lib.config.identity_font||'huangcao')+',xinwei}',0);
				if(lib.config.cardtext_font&&lib.config.cardtext_font!='default'){
					ui.css.styles.sheet.insertRule('.card div:not(.info):not(.background) {font-family: '+lib.config.cardtext_font+';}',0);
				}
				if(lib.config.global_font&&lib.config.global_font!='default'){
					ui.css.styles.sheet.insertRule('#window {font-family: '+lib.config.global_font+',xinwei}',0);
					ui.css.styles.sheet.insertRule('#window #control{font-family: STHeiti,SimHei,Microsoft JhengHei,Microsoft YaHei,WenQuanYi Micro Hei,Suits,Helvetica,Arial,sans-serif}',0);
				}
				switch(lib.config.glow_phase){
					case 'yellow':ui.css.styles.sheet.insertRule('#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgb(217, 152, 62) 0 0 15px, rgb(217, 152, 62) 0 0 15px !important;}',0);break;
					case 'green':ui.css.styles.sheet.insertRule('#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgba(10, 155, 67, 1) 0 0 15px, rgba(10, 155, 67, 1) 0 0 15px !important;}',0);break;
					case 'purple':ui.css.styles.sheet.insertRule('#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgb(189, 62, 170) 0 0 15px, rgb(189, 62, 170) 0 0 15px !important;}',0);break;
				}
			},
			layout:function(layout,nosave){
				if(layout=='default') layout='mobile';
				if(!nosave) game.saveConfig('layout',layout);
				game.layout=layout;
				ui.arena.hide();
				setTimeout(function(){
					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;i<game.players.length;i++){
						if(get.is.linked2(game.players[i])){
							if(game.players[i].classList.contains('linked')){
								game.players[i].classList.remove('linked');
								game.players[i].classList.add('linked2');
							}
						}
						else{
							if(game.players[i].classList.contains('linked2')){
								game.players[i].classList.remove('linked2');
								game.players[i].classList.add('linked');
							}
						}
					}
					if(game.layout=='long'||game.layout=='long2'){
						ui.arena.classList.add('long');
					}
					else{
						ui.arena.classList.remove('long');
					}
					if(lib.config.player_border!='wide'||game.layout=='long'||game.layout=='long2'){
						ui.arena.classList.add('slim_player');
					}
					else{
						ui.arena.classList.remove('slim_player');
					}
					if(lib.config.player_border=='normal'&&lib.config.mode!='brawl'&&(game.layout=='long'||game.layout=='long2')){
						ui.arena.classList.add('lslim_player');
					}
					else{
						ui.arena.classList.remove('lslim_player');
					}
					if(lib.config.player_border=='slim'){
						ui.arena.classList.add('uslim_player');
					}
					else{
						ui.arena.classList.remove('uslim_player');
					}
					if(lib.config.player_border=='narrow'){
						ui.arena.classList.add('mslim_player');
					}
					else{
						ui.arena.classList.remove('mslim_player');
					}
					ui.updatej();
					ui.updatem();
					setTimeout(function(){
						ui.arena.show();
						if(game.me) game.me.update();
						setTimeout(function(){
							ui.updatex();
						},500);
						setTimeout(function(){
							ui.updatec();
						},1000);
					},100);
				},500);
			},
			background:function(){
				if(lib.config.image_background_random){
					var list=[];
					for(var i in lib.configMenu.appearence.config.image_background.item){
						if(i=='default') continue;
						list.push(i);
					}
					list.remove(lib.config.image_background);
					localStorage.setItem(lib.configprefix+'background',JSON.stringify(list));
				}
				else if(lib.config.image_background&&lib.config.image_background!='default'&&!lib.config.image_background.startsWith('custom_')){
					localStorage.setItem(lib.configprefix+'background',lib.config.image_background);
				}
				else if(lib.config.image_background=='default'&&lib.config.theme=='simple'){
					localStorage.setItem(lib.configprefix+'background','ol_bg');
				}
				else{
					localStorage.removeItem(lib.configprefix+'background');
				}
			},
			parsex:function(item){
				//by 诗笺、Tipx-L
				function Legacy(func){
					//Remove all comments
					//移除所有注释
					var 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);
					//func中要写步骤的话,必须要写step 0
					if(str.indexOf('step 0')==-1){
						str='{if(event.step==1) {event.finish();return;}\n'+str;
					}else{
						var skip=0;
						//每层最多找99个step
						for (var k=0;k<99;k++) {
							//正则表达式
							var reg=new RegExp(`['"]step ${k}['"]`);
							var result=str.slice(skip).match(reg);
							if(result==null) break;
							var insertStr;
							if(k==0){
								insertStr=`switch(step){case 0:`;
							}else{
								insertStr=`break;case ${k}:`;
							}
							var copy=str;
							copy=copy.slice(0,skip+result.index)+insertStr+copy.slice(skip+result.index+result[0].length);
							//测试是否有错误
							try{
								new Function(copy);
								str=copy;
								skip+=result.index+insertStr.length;
							}catch(error){
								k--;
								skip+=result.index+result[0].length;
							}
						}
						str=`if(event.step==${k}){event.finish();return;}`+str;
					}
					return (new Function('event','step','source','player','target','targets',
						'card','cards','skill','forced','num','trigger','result',
						'_status','lib','game','ui','get','ai',str));
				}
				switch(typeof item){
					case "object":
						if(Array.isArray(item)){
							let lastEvent=null;
							return (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];
								lastEvent=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);
							}
						}
						else{
							if(Symbol.iterator in item) return lib.init.parsex(Array.from(item));
							if("toString" in item) 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 (event,step,source,player,target,targets,card,cards,skill,forced,num,trigger,result,_status,lib,game,ui,get,ai)=>{
								if(!gen)gen=item(event,{
									event:event,
									step:step,
									source:source,
									player:player,
									target:target,
									targets:targets,
									card:card,
									cards:cards,
									skill:skill,
									forced:forced,
									num:num,
									trigger:trigger,
									result:result
								});
								var res=gen.next((lastEvent&&("result" in lastEvent))?lastEvent.result:null);
								if(res.done) event.finish();
								else lastEvent=res.value;
							}
						}
					default:
						return Legacy(item);
				}
			},
			eval:function(func){
				if(typeof func=='function'){
					return eval('('+func.toString()+')');
				}
				else if(typeof func=='object'){
					for(var i in func){
						if(func.hasOwnProperty(i)){
							func[i]=lib.init.eval(func[i]);
						}
					}
				}
				return func;
			},
			encode:function(strUni){
				var strUtf = strUni.replace(
					/[\u0080-\u07ff]/g,function(c){
					var cc = c.charCodeAt(0);
					return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f);
				});
				strUtf = strUtf.replace(
					/[\u0800-\uffff]/g,function(c) {
					var cc = c.charCodeAt(0);
					return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f);
				});
				return btoa(strUtf);
			},
			decode:function(str){
				var strUtf=atob(str);
				var strUni = strUtf.replace(
					/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,function(c) {
					var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f);
					return String.fromCharCode(cc);
				});
				strUni = strUni.replace(
					/[\u00c0-\u00df][\u0080-\u00bf]/g,function(c){
					var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
					return String.fromCharCode(cc);
				});
				return strUni;
			},
			stringify:function(obj){
				var str='{'
				for(var i in obj){
					str+='"'+i+'":'
					if(Object.prototype.toString.call(obj[i])=='[object Object]'){
						str+=lib.init.stringify(obj[i]);
					}
					else if(typeof obj[i]=='function'){
						str+=obj[i].toString();
					}
					else{
						str+=JSON.stringify(obj[i]);
					}
					str+=','
				}
				str+='}';
				return str;
			},
			stringifySkill:function(obj){
				var str='';
				for(var i in obj){
					str+=i+':'
					if(Object.prototype.toString.call(obj[i])=='[object Object]'){
						str+='{\n'+lib.init.stringifySkill(obj[i])+'}';
					}
					else if(typeof obj[i]=='function'){
						str+=obj[i].toString().replace(/\t/g,'');
					}
					else{
						str+=JSON.stringify(obj[i]);
					}
					str+=',\n'
				}
				return str;
			}
		},
		cheat:{
			i:function(){
				window.cheat=lib.cheat;
				window.game=game;
				window.ui=ui;
				window.get=get;
				window.ai=ai;
				window.lib=lib;
				window._status=_status;
			},
			dy:function(){
				var next=game.me.next;
				for(var i=0;i<10;i++){
					if(next.identity!='zhu'){
						break;
					}
					next=next.next;
				}
				next.die();
			},
			x:function(){
				var gl=function(dir,callback){
					var files=[],folders=[];
					dir='/Users/widget/Documents/extension/'+dir;
					lib.node.fs.readdir(dir,function(err,filelist){
						for(var i=0;i<filelist.length;i++){
							if(filelist[i][0]!='.'&&filelist[i][0]!='_'){
								if(lib.node.fs.statSync(dir+'/'+filelist[i]).isDirectory()){
									folders.push(filelist[i]);
								}
								else{
									files.push(filelist[i]);
								}
							}
						}
						callback(folders,files);
					});
				}
				var args=Array.from(arguments);
				for(var i=0;i<args.length;i++){
					args[i]=args[i][0];
				}
				gl('',function(list){
					if(args.length){
						for(var i=0;i<list.length;i++){
							if(!args.contains(list[i][0])){
								list.splice(i--,1);
							}
						}
					}
					if(list.length){
						for(var i=0;i<list.length;i++){
							(function(str){
								gl(str,function(folders,files){
									if(files.length>1){
										for(var i=0;i<files.length;i++){
											if(files[i].includes('extension.js')){
												files.splice(i--,1);
											}
											else{
												if(i%5==0){
													str+='\n\t\t\t';
												}
												str+='"'+files[i]+'",';
											}
										}
										console.log(str.slice(0,str.length-1));
									}
								});
							}(list[i]));
						}
					}
				});
			},
			cfg:function(){
				var mode=lib.config.all.mode.slice(0);
				mode.remove('connect');
				mode.remove('brawl');
				var banned=['shen_guanyu','shen_caocao','caopi','re_daqiao','caorui',
					'daqiao','lingcao','liuzan','lusu','luxun','yanwen','zhouyu','ns_wangyue','gw_yenaifa',
					'old_caozhen','swd_jiangziya','xuhuang','maliang','guojia','simayi','swd_kangnalishi','hs_siwangzhiyi','hs_nozdormu','old_zhuzhi'];
				var bannedcards=['zengbin'];
				var favs=["hs_tuoqi","hs_siwangxianzhi","hs_xukongzhiying","hs_hsjiasha","gjqt_xieyi","gjqt_yunwuyue","gjqt_beiluo",
					"gjqt_cenying","shen_lvmeng","shen_zhaoyun","shen_zhugeliang","ow_ana","chenlin","ns_guanlu","hs_guldan","swd_guyue",
					"pal_jiangyunfan","mtg_jiesi","swd_lanyin","pal_liumengli","swd_muyun","pal_nangonghuang","swd_muyue","pal_murongziying",
					"swd_qiner","pal_shenqishuang","hs_taisi","wangji","pal_xingxuan","xunyou","hs_yelise","pal_yuejinzhao","pal_yueqi",
					"gjqt_yuewuyi","swd_yuxiaoxue","ow_zhaliya","zhangchunhua","hs_zhihuanhua","swd_zhiyin","old_zhonghui","gjqt_bailitusu",
					"hs_barnes","ow_dva","swd_hengai","pal_jushifang","hs_kazhakusi","hs_lafamu","ow_liekong","hs_lreno","pal_mingxiu",
					"swd_murongshi","gw_oudimu","gjqt_ouyangshaogong","hs_pyros","qinmi","gw_sanhanya","hs_selajin","swd_shuwaner",
					"swd_situqiang","hs_xialikeer","pal_xuejian","swd_yuchiyanhong","swd_yuwentuo","swd_zhaoyun","zhugeliang","gw_aigeleisi",
					"gw_aimin","gjqt_aruan","hs_aya","swd_cheyun","swd_chenjingchou","gw_diandian","swd_huzhongxian","hs_jinglinglong",
					"hs_kaituozhe","hs_kalimosi","gw_linjing","ow_luxiao","re_luxun","hs_morgl","swd_sikongyu","hs_sthrall","sunquan",
					"sunshangxiang","gw_yioufeisisp","gw_yisilinni","hs_yogg","hs_ysera","pal_yuntianhe","zhugejin","zhugeke","gw_zhuoertan",
					"hs_anduin","swd_anka","ow_banzang","ow_chanyata","diaochan","swd_duguningke","sp_diaochan","hetaihou","ns_huamulan",
					"swd_huanglei","swd_huanyuanzhi","re_huatuo","gw_huoge","pal_jiangcheng","yj_jushou","swd_kendi","yxs_libai",
					"mtg_lilianna","xin_liru","liuxie","pal_lixiaoyao","pal_longkui","ns_nanhua","swd_qi","swd_septem","gw_shasixiwusi",
					"ow_tianshi","swd_weida","gjqt_xiayize","swd_xiyan","hs_xsylvanas","hs_yelinlonghou","ow_yuanshi","zuoci"];
				var vintage=['tianjian','shuiyun','zhuyue','zhimeng','poyun','qianfang','xfenxin','danqing','ywuhun','tianwu','xuelu',
					'shahun','yuling','duhun','liaoyuan','touxi','wangchen','poyue','kunlunjing','huanhun','yunchou','tuzhen','cyqiaoxie',
					'mufeng','duanyi','guozao','yaotong','pozhen','tanlin','susheng','jikong','shouyin','jilve','hxunzhi','huodan','shanxian',
					'ziyu','kuoyin','feiren','zihui','jidong','baoxue','aqianghua','maoding','bfengshi','zhongdun','pingzhang','maichong',
					'guozai','jingxiang','yuelu','liechao','fengnu','hanshuang','enze','malymowang','xshixin','qingzun'];
				var favmodes=["versus|three", "versus|four", "versus|two", "chess|combat"];
				for(var i=0;i<mode.length;i++){
					game.saveConfig(mode[i]+'_banned',banned);
					game.saveConfig(mode[i]+'_bannedcards',bannedcards);
				}
				var characters=lib.config.all.characters.slice(0);
				characters.remove('standard');
				characters.remove('old');
				game.saveConfig('vintageSkills', vintage);
				game.saveConfig('favouriteCharacter',favs);
				game.saveConfig('favouriteMode',favmodes);
				game.saveConfig('theme','simple');
				game.saveConfig('player_border', 'slim');
				game.saveConfig('cards',lib.config.all.cards);
				game.saveConfig('characters',characters);
				game.saveConfig('change_skin',false);
				game.saveConfig('show_splash','off');
				game.saveConfig('show_favourite',false);
				game.saveConfig('animation', false);
				game.saveConfig('hover_all', false);
				game.saveConfig('asset_version', 'v1.9');
				// game.saveConfig('characters',lib.config.all.characters);
				// game.saveConfig('cards',lib.config.all.cards);
				game.saveConfig('plays',['cardpile']);
				game.saveConfig('skip_shan',false);
				game.saveConfig('tao_enemy',true);
				game.saveConfig('layout','long2');
				game.saveConfig('hp_style','ol');
				game.saveConfig('background_music','music_off');
				game.saveConfig('background_audio',false);
				game.saveConfig('background_speak',false);
				game.saveConfig('show_volumn',false);
				game.saveConfig('show_replay',true);
				game.saveConfig('autostyle',true);
				game.saveConfig('debug',true);
				game.saveConfig('dev',true);
				if(!lib.device){
					game.saveConfig('sync_speed',false);
				}
				game.reload();
			},
			o:function(){
				ui.arena.classList.remove('observe');
			},
			pt:function(){
				var list=Array.from(arguments);
				while(list.length){
					var card=cheat.gn(list.pop());
					if(card) ui.cardPile.insertBefore(card,ui.cardPile.firstChild);
				}
			},
			q:function(){
				// if(lib.config.layout!='mobile') lib.init.layout('mobile');
				if(arguments.length==0){
					var style=ui.css.card_style;
					if(lib.config.card_style!='simple'){
						lib.config.card_style='simple';
						ui.css.card_style=lib.init.css(lib.assetURL+'theme/style/card','simple');
					}
					else{
						lib.config.card_style='default';
						ui.css.card_style=lib.init.css(lib.assetURL+'theme/style/card','default');
					}
					style.remove();
				}
				else{
					for(var i=0;i<arguments.length;i++){
						cheat.g(arguments[i]);
					}
				}
				ui.arena.classList.remove('selecting');
				ui.arena.classList.remove('tempnoe');
			},
			p:function(name,i,skin){
				var list=['swd','hs','pal','gjqt','ow','gw'];
				if(!lib.character[name]){
					for(var j=0;j<list.length;j++){
						if(lib.character[list[j]+'_'+name]){
							name=list[j]+'_'+name;break;
						}
					}
				}
				if(skin){
					lib.config.skin[name]=skin
				}
				var target;
				if(typeof i=='number'){
					target=game.players[i];
				}
				else{
					target=game.me.next;
				}
				if(!lib.character[name]){
					target.node.avatar.setBackground(name,'character');
					target.node.avatar.show();
				}
				else{
					target.init(name);
				}
				if(i===true){
					if(lib.config.layout=='long2'){
						lib.init.layout('mobile');
					}
					else{
						lib.init.layout('long2');
					}
				}
			},
			e:function(){
				var cards=[],target;
				for(var i=0;i<arguments.length;i++){
					if(get.itemtype(arguments[i])=='player'){
						target=arguments[i];
					}
					else{
						cards.push(game.createCard(arguments[i]));
					}
				}
				if(!cards.length){
					cards.push(game.createCard('qilin'));
					cards.push(game.createCard('bagua'));
					cards.push(game.createCard('dilu'));
					cards.push(game.createCard('chitu'));
					cards.push(game.createCard('muniu'));
				}
				target=target||game.me;
				for(var i=0;i<cards.length;i++){
					var card=target.getEquip(cards[i]);
					if(card){
						card.discard();
						target.removeEquipTrigger(card);
					}
					target.$equip(cards[i]);
				}
			},
			c:function(){
				(function(){
					var a=0,b=0,c=0,d=0,e=0,f=0,g=0;
					var sa=0,sb=0,sc=0,sd=0,se=0,sf=0,sg=0;
					for(var i in lib.character){
						switch(lib.character[i][1]){
							case 'wei':a++;if(lib.config.banned.contains(i)) sa++;break;
							case 'shu':b++;if(lib.config.banned.contains(i)) sb++;break;
							case 'wu':c++;if(lib.config.banned.contains(i)) sc++;break;
							case 'qun':d++;if(lib.config.banned.contains(i)) sd++;break;
							case 'jin':g++;if(lib.config.banned.contains(i)) sg++;break;
							case 'western':e++;if(lib.config.banned.contains(i)) se++;break;
							case 'key':f++;if(lib.config.banned.contains(i)) sf++;break;
						}
					}
					console.log('魏:'+(a-sa)+'/'+a);
					console.log('蜀:'+(b-sb)+'/'+b);
					console.log('吴:'+(c-sc)+'/'+c);
					console.log('群:'+(d-sd)+'/'+d);
					console.log('晋:'+(g-sg)+'/'+g);
					console.log('西:'+(e-se)+'/'+e);
					console.log('键:'+(f-sf)+'/'+f);
					console.log('已启用:'+((a+b+c+d+e+f)-(sa+sb+sc+sd+se+sf))+'/'+(a+b+c+d+e+f));
				}());
				(function(){
					var a=0,b=0,c=0,d=0;
					var aa=0,bb=0,cc=0,dd=0;
					var sa=0,sb=0,sc=0,sd=0;
					var sha=0,shan=0,tao=0,jiu=0,wuxie=0,heisha=0,hongsha=0;
					var num={1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0};
					for(var i in lib.card){
						if(get.objtype(lib.card[i])=='object'&&lib.translate[i+'_info']){
							switch(lib.card[i].type){
								case 'basic':a++;break;
								case 'trick':b++;break;
								case 'equip':c++;break;
								default:d++;break;
							}
						}
					}
					for(var i=0;i<lib.card.list.length;i++){
						if(typeof lib.card[lib.card.list[i][2]]=='object'){
							switch(lib.card[lib.card.list[i][2]].type){
								case 'basic':aa++;break;
								case 'trick':case 'delay':bb++;break;
								case 'equip':cc++;break;
								default:dd++;break;
							}
							switch(lib.card.list[i][0]){
								case 'heart':sa++;break;
								case 'diamond':sb++;break;
								case 'club':sc++;break;
								case 'spade':sd++;break;
							}
							if(lib.card.list[i][2]=='sha'){
								sha++;
								if(lib.card.list[i][0]=='club'||lib.card.list[i][0]=='spade'){
									heisha++;
								}
								else{
									hongsha++;
								}
							}
							if(lib.card.list[i][2]=='shan'){
								shan++;
							}
							if(lib.card.list[i][2]=='tao'){
								tao++;
							}
							if(lib.card.list[i][2]=='jiu'){
								jiu++;
							}
							if(lib.card.list[i][2]=='wuxie'){
								wuxie++;
							}
							num[lib.card.list[i][1]]++;
						}
					}
					var str='基本牌'+aa+'; '+'锦囊牌'+bb+'; '+'装备牌'+cc+'; '+'其它牌'+dd
					console.log(str);
					str='红桃牌'+sa+'; '+'方片牌'+sb+'; '+'梅花牌'+sc+'; '+'黑桃牌'+sd
					console.log(str);
					str='杀'+sha+'; '+'黑杀'+heisha+'; '+'红杀'+hongsha+'; '+'闪'+shan+'; '+'桃'+tao+'; '+'酒'+jiu+'; '+'无懈'+wuxie
					console.log(str);
					if(arguments[1]){
						for(var i=1;i<=13;i++){
							if(i<10){
								console.log(i+' ',num[i]);
							}
							else{
								console.log(i,num[i]);
							}
						}
					}
					var arr=[];
					for(var i=1;i<=13;i++){
						arr.push(num[i]);
					}
					console.log((a+b+c+d)+'/'+(aa+bb+cc+dd),...arr)
				}());
			},
			id:function(){
				game.showIdentity();
			},
			b:function(){
				if(!ui.dialog||!ui.dialog.buttons) return;
				for(var i=0;i<Math.min(arguments.length,ui.dialog.buttons.length);i++){
					ui.dialog.buttons[i].link=arguments[i];
				}
			},
			uy:function(me){
				if(me){
					game.me.useCard({name:'spell_yexinglanghun'},game.me);
				}
				else{
					var enemy=game.me.getEnemy();
					enemy.useCard({name:'spell_yexinglanghun'},enemy);
				}
			},
			gs:function(name,act){
				var card=game.createCard('spell_'+(name||'yexinglanghun'));
				game.me.node.handcards1.appendChild(card);
				if(!act){
					game.me.actused=-99;
				}
				ui.updatehl();
				delete _status.event._cardChoice;
				delete _status.event._targetChoice;
				delete _status.event._skillChoice;
				setTimeout(game.check,300);
			},
			gc:function(name,act){
				var card=game.createCard('stone_'+(name||'falifulong')+'_stonecharacter');
				game.me.node.handcards1.appendChild(card);
				if(!act){
					game.me.actused=-99;
				}
				ui.updatehl();
				delete _status.event._cardChoice;
				delete _status.event._targetChoice;
				delete _status.event._skillChoice;
				setTimeout(game.check,300);
			},
			a:function(bool){
				if(lib.config.test_game){
					game.saveConfig('test_game');
				}
				else{
					if(bool){
						if(typeof bool==='string'){
							game.saveConfig('test_game',bool);
						}
						else{
							game.saveConfig('test_game','_');
						}
					}
					else{
						game.saveConfig('test_game',true);
					}
				}
				game.reload();
			},
			as:function(){
				ui.window.classList.remove('testing');
				var bg=ui.window.querySelector('.pausedbg');
				if(bg){
					bg.remove();
				}
			},
			uj:function(){
				cheat.e('qilin');
				game.me.next.useCard({name:'jiedao'},[game.me,game.me.previous]);
			},
			u:function(){
				var card={name:'sha'},source=game.me.next,targets=[];
				for(var i=0;i<arguments.length;i++){
					if(get.itemtype(arguments[i])=='player'){
						source=arguments[i];
					}
					else if(Array.isArray(arguments[i])){
						targets=arguments[i];
					}
					else if(typeof arguments[i]=='object'&&arguments[i]){
						card=arguments[i];
					}
					else if(typeof arguments[i]=='string'){
						card={name:arguments[i]}
					}
				}
				if(!targets.length) targets.push(game.me);
				source.useCard(game.createCard(card.name,card.suit,card.number,card.nature),targets);
			},
			r:function(bool){
				var list=['s','ap','a','am','bp','b','bm','c','d'];
				var str='';
				for(var i=0;i<list.length;i++){
					if(str) str+=' 、 ';
					str+=list[i]+'-'+lib.rank[list[i]].length;
				}
				console.log(str);
				for(var i in lib.characterPack){
					if(!bool&&lib.config.all.sgscharacters.contains(i)) continue;
					var map={};
					var str='';
					for(var j in lib.characterPack[i]){
						var rank=get.rank(j);
						if(!map[rank]){
							map[rank]=1;
						}
						else{
							map[rank]++;
						}
					}
					for(var j=0;j<list.length;j++){
						if(map[list[j]]){
							if(str) str+=' 、 ';
							str+=list[j]+'-'+map[list[j]];
						}
					}
					if(str){
						console.log(lib.translate[i+'_character_config']+':'+str);
					}
				}

				var list=lib.rank.s.concat(lib.rank.ap).concat(lib.rank.a).concat(lib.rank.am).
					concat(lib.rank.bp).concat(lib.rank.b).concat(lib.rank.bm).concat(lib.rank.c).concat(lib.rank.d);
				Object.keys(lib.character).forEach(key=>{
					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;i<arguments.length;i++){
					if(i>0&&typeof arguments[i]=='number'){
						for(var j=0;j<arguments[i]-1;j++){
							cheat.gx(arguments[i-1]);
						}
					}
					else{
						cheat.gx(arguments[i]);
					}
				}
			},
			ga:function(type){
				for(var i in lib.card){
					if(lib.card[i].type==type||lib.card[i].subtype==type){
						cheat.g(i);
					}
				}
			},
			gg:function(){
				for(var i=0;i<game.players.length;i++){
					for(var j=0;j<arguments.length;j++){
						cheat.gx(arguments[j],game.players[i]);
					}
				}
			},
			gx:function(name,target){
				target=target||game.me;
				var card=cheat.gn(name);
				if(!card) return;
				target.node.handcards1.appendChild(card);
				delete _status.event._cardChoice;
				delete _status.event._targetChoice;
				delete _status.event._skillChoice;
				game.check();
				target.update();
				ui.updatehl();
			},
			gn:function(name){
				var nature=null;
				var suit=null;
				var suits=['club','spade','diamond','heart'];
				for(var i=0;i<suits.length;i++){
					if(name.startsWith(suits[i])){
						suit=suits[i];
						name=name.slice(suits[i].length);
						break;
					}
				}
				if(name.startsWith('red')){
					name=name.slice(3);
					suit=['diamond','heart'].randomGet();
				}
				if(name.startsWith('black')){
					name=name.slice(5);
					suit=['spade','club'].randomGet();
				}

				if(name=='huosha'){
					name='sha';
					nature='fire';
				}
				else if(name=='leisha'){
					name='sha';
					nature='thunder';
				}
				if(!lib.card[name]){
					return null;
				}
				return game.createCard(name,suit,null,nature);
			},
			ge:function(target){
				if(target){
					cheat.gx('zhuge',target);
					cheat.gx('qinglong',target);
					cheat.gx('bagua',target);
					cheat.gx('dilu',target);
					cheat.gx('chitu',target);
					cheat.gx('muniu',target);
				}
				else{
					cheat.g('zhuge');
					cheat.g('qinglong');
					cheat.g('bagua');
					cheat.g('dilu');
					cheat.g('chitu');
					cheat.g('muniu');
				}
			},
			gj:function(){
				cheat.g('shandian');
				cheat.g('huoshan');
				cheat.g('hongshui');
				cheat.g('lebu');
				cheat.g('bingliang');
				cheat.g('guiyoujie');
			},
			gf:function(){
				for(var i in lib.card){
					if(lib.card[i].type=='food'){
						cheat.g(i);
					}
				}
			},
			d:function(num,target){
				if(num==undefined) num=1;
				var cards=get.cards(num);
				for(var i=0;i<num;i++){
					var card=cards[i];
					game.me.node.handcards1.appendChild(card);
					delete _status.event._cardChoice;
					delete _status.event._targetChoice;
					delete _status.event._skillChoice;
					game.check();
					game.me.update();
					ui.updatehl();
				}
			},
			s:function(){
				for(var i=0;i<arguments.length;i++){
					game.me.addSkill(arguments[i],true);
				}
				delete _status.event._cardChoice;
				delete _status.event._targetChoice;
				delete _status.event._skillChoice;
				game.check();
			},
			t:function(num){
				if(game.players.contains(num)){
					num=game.players.indexOf(num);
				}
				if(num==undefined){
					for(var i=0;i<game.players.length;i++) cheat.t(i);
					return;
				}
				var player=game.players[num];
				var cards=player.getCards('hej');
				for(var i=0;i<cards.length;i++){
					cards[i].discard();
				}
				player.removeEquipTrigger();
				player.update();
			},
			to:function(){
				for(var i=0;i<game.players.length;i++){
					if(game.players[i]!=game.me){
						cheat.t(i);
					}
				}
			},
			tm:function(){
				for(var i=0;i<game.players.length;i++){
					if(game.players[i]==game.me){
						cheat.t(i);
					}
				}
			},
			k:function(i){
				if(i==undefined) i=1;
				game.players[i].hp=1;
				cheat.t(i);
				cheat.g('juedou');
			},
			z:function(name){
				switch(name){
					case 'cc':name='re_caocao';break;
					case 'lb':name='re_liubei';break;
					case 'sq':name='sunquan';break;
					case 'dz':name='dongzhuo';break;
					case 'ys':name='re_yuanshao';break;
					case 'zj':name='sp_zhangjiao';break;
					case 'ls':name='liushan';break;
					case 'sc':name='sunce';break;
					case 'cp':name='caopi';break;
					case 'cr':name='caorui';break;
					case 'sx':name='sunxiu';break;
					case 'lc':name='liuchen';break;
					case 'sh':name='sunhao';break;
				}
				game.zhu.init(name);
				game.zhu.maxHp++;
				game.zhu.hp++;
				game.zhu.update();
			},
		},
		translate:{
			flower:'鲜花',
			egg:'鸡蛋',
			wine:'酒杯',
			shoe:'拖鞋',
			yuxisx:'玉玺',
			jiasuo:'枷锁',
			junk:'平凡',
			common:'普通',
			rare:'精品',
			epic:'史诗',
			legend:'传说',
			default:"默认",
			special:'特殊',
			zhenfa:'阵法',
			aozhan:"鏖战",
			mode_derivation_card_config:'衍生',
			mode_banned_card_config:'禁卡',
			mode_favourite_character_config:'收藏',
			mode_banned_character_config:'禁将',
			heart:"♥︎",
			diamond:"♦︎",
			spade:"♠︎",
			club:"♣︎",
			none:'◈',
			ghujia:'护甲',
			ghujia_bg:'甲',
			heart2:"红桃",
			diamond2:"方片",
			spade2:"黑桃",
			club2:"梅花",
			none2:'无色',
			red:'红色',
			black:'黑色',
			ok:"确定",
			ok2:"确定",
			cancel:"取消",
			cancel2:"取消",
			restart:"重新开始",
			setting:"设置",
			start:"开始",
			random:"随机",
			_out:'无效',
			agree:'同意',
			refuse:'拒绝',
			fire:"火",
			thunder:"雷",
			poison:"毒",
			kami:'神',
			ice:'冰',
			stab:'刺',
			wei:'魏',
			shu:'蜀',
			wu:'吴',
			qun:'群',
			shen:'神',
			western:'西',
			key:'键',
			jin:'晋',
			double:'双',
			wei2:'魏国',
			shu2:'蜀国',
			wu2:'吴国',
			qun2:'群雄',
			shen2:'神明',
			western2:'西方',
			key2:'KEY',
			jin2:'晋朝',
			double2:'双势力',
			male:'男',
			female:'女',
			mad:'混乱',
			mad_bg:'疯',
			draw_card:'摸牌',
			discard_card:'弃牌',
			take_damage:'受伤害',
			reset_character:'复原武将牌',
			recover_hp:'回复体力',
			lose_hp:'流失体力',
			get_damage:'受伤害',
			weiColor:"#b0d0e2",
			shuColor:"#ffddb9",
			wuColor:"#b2d9a9",
			qunColor:"#f6f6f6",
			shenColor:"#ffe14c",
			westernColor:"#ffe14c",
			jinColor:"#ffe14c",
			keyColor:"#c9b1fd",
			basic:'基本',
			equip:'装备',
			trick:'锦囊',
			delay:'延时锦囊',
			character:'角色',
			revive:'复活',
			equip1:'武器',
			equip2:'防具',
			equip3:'防御马',
			'equip3_4':'坐骑',
			equip4:'攻击马',
			equip5:'宝物',
			equip6:'特殊装备',
			zero:'零',
			one:'一',
			two:'二',
			three:'三',
			four:'四',
			five:'五',
			six:'六',
			seven:'七',
			eight:'八',
			nine:'九',
			ten:'十',
			_recasting:'重铸',
			_lianhuan:'连环',
			_lianhuan2:'连环',
			_kamisha:'神杀',
			_icesha:'冰杀',
			qianxing:'潜行',
			mianyi:'免疫',
			fengyin:'封印',
			baiban:'白板',
			_disableJudge:"判定区",
			
			xiaowu_emotion:'小无表情',
			guojia_emotion:'郭嘉表情',
			zhenji_emotion:'甄姬表情',
			shibing_emotion:'士兵表情',
			xiaosha_emotion:'小杀表情',
			xiaotao_emotion:'小桃表情',
			xiaojiu_emotion:'小酒表情',
			xiaokuo_emotion:'小扩表情',

			pause:'暂停',
			config:'选项',
			auto:'托管',

			unknown:'未知',
			unknown0:'一号位',
			unknown1:'二号位',
			unknown2:'三号位',
			unknown3:'四号位',
			unknown4:'五号位',
			unknown5:'六号位',
			unknown6:'七号位',
			unknown7:'八号位',
			
			feichu_equip1:"已废除",
			feichu_equip1_info:"武器栏已废除",
			feichu_equip2:"已废除",
			feichu_equip2_info:"防具栏已废除",
			feichu_equip3:"已废除",
			feichu_equip3_info:"防御坐骑栏已废除",
			feichu_equip4:"已废除",
			feichu_equip4_info:"攻击坐骑栏已废除",
			feichu_equip5:"已废除",
			feichu_equip5_info:"宝物栏已废除",
			feichu_equip1_bg:"废",
			feichu_equip2_bg:"废",
			feichu_equip3_bg:"废",
			feichu_equip4_bg:"废",
			feichu_equip5_bg:"废",
			disable_judge:'已废除',
			disable_judge_info:'判定区已废除',
			disable_judge_bg:'废',
			pss:'手势',
			pss_paper:'布',
			pss_scissor:'剪刀',
			pss_stone:'石头',
			pss_paper_info:'石头剪刀布时的一种手势。克制石头,但被剪刀克制。',
			pss_scissor_info:'石头剪刀布时的一种手势。克制布,但被石头克制。',
			pss_stone_info:'石头剪刀布时的一种手势。克制剪刀,但被布克制。',
			renku:'仁库',
			group_wei:"魏势力",
			group_shu:"蜀势力",
			group_wu:"吴势力",
			group_qun:"群势力",
			group_key:"键势力",
			group_jin:"晋势力",
			group_wei_bg:"魏",
			group_shu_bg:"蜀",
			group_wu_bg:"吴",
			group_qun_bg:"群",
			group_key_bg:"键",
			group_jin_bg:"晋",
			zhengsu:'整肃',
			zhengsu_leijin:'擂进',
			zhengsu_bianzhen:'变阵',
			zhengsu_mingzhi:'鸣止',
			zhengsu_leijin_info:'回合内所有于出牌阶段使用的牌点数递增且不少于三张。',
			zhengsu_bianzhen_info:'回合内所有于出牌阶段使用的牌花色相同且不少于两张。',
			zhengsu_mingzhi_info:'回合内所有于弃牌阶段弃置的牌花色均不相同且不少于两张。',
			db_atk:'策略',
			db_atk1:'全军出击',
			db_atk2:'分兵围城',
			db_def:'策略',
			db_def1:'奇袭粮道',
			db_def2:'开城诱敌',
			cooperation_damage:'同仇',
			cooperation_damage_info:'双方累计造成至少4点伤害',
			cooperation_draw:'并进',
			cooperation_draw_info:'双方累计摸至少8张牌',
			cooperation_discard:'疏财',
			cooperation_discard_info:'双方累计弃置至少4种花色的牌',
			cooperation_use:'戮力',
			cooperation_use_info:'双方累计使用至少4种花色的牌',
			charge:'蓄力值',
			expandedSlots:'扩展装备栏',
		},
		element:{
			content:{
				emptyEvent:function(){
					event.trigger(event.name);
				},
				//增加明置手牌
				addShownCards:()=>{
					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<cards.length){
						event.card=cards[num];
						event.trigger('gift');
					}
					else{
						game.delayx();
						event.finish();
					}
					'step 2'
					if(event.deniedGifts.includes(card)){
						game.log(target,'拒绝了',player,'赠予的',card);
						event.trigger('giftDeny');
						player.loseToDiscardpile(card).log=false;
						event.trigger('giftDenied');
						return;
					}
					game.log(player,'将',card,'赠予了',target);
					player.$give(card,target,false);
					game.delay(0.5);
					event.trigger('giftAccept');
					if(get.type(card,false)=='equip') target.equip(card).log=false;
					else target.gain(card,player).visible=true;
					event.trigger('giftAccepted');
					'step 3'
					event.num++;
					event.goto(1);
				},
				//Recast
				//重铸
				recast:()=>{
					'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=[...new Set(event.slots)].sort();
					if(!event.slots.length) event.finish();
					'step 1'
					var slot=event.slotsx[event.num];
					var left=player.countEnabledSlot(slot),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]) player.disabledSlots[slot]=0;
						player.disabledSlots[slot]+=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){
										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.num<event.slotsx.length) event.goto(1);
					else{
						player.$syncDisable();
						if(cards.length>0) 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=[...new Set(event.slots)].sort();
					for(var slot of slotsx){
						var expand=get.numOf(event.slots,slot);
						game.log(player,'获得了'+get.cnNumber(expand)+'个额外的','#g'+get.translation(slot)+'栏');
						if(!player.expandedSlots) player.expandedSlots={};
						if(!player.expandedSlots[slot]) player.expandedSlots[slot]=0;
						player.expandedSlots[slot]+=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=[...new Set(event.slots)].sort();
						}
					}
					else event.goto(4);
					'step 1'
					var slot=event.slotsx[event.num];
					var left=player.countEquipableSlot(slot),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){
										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.num<event.slotsx.length) event.goto(1);
					'step 4'
					event.result=cards;
				},
				//装备牌
				equip:function(){
					"step 0"
					var owner=get.owner(card)
					if(owner){
						event.owner=owner;
						owner.lose(card,ui.special,'visible').set('type','equip').set('getlx',false);
					}
					else if(get.position(card)=='c') event.updatePile=true;
					"step 1"
					if(event.cancelled){
						event.finish();
						return;
					}
					if(card.destroyed){
						if(player.hasSkill(card.destroyed)){
							delete card.destroyed;
						}
						else{
							event.finish();
							return;
						}
					}
					else if(event.owner){
						if(event.owner.getCards('hejsx').contains(card)){
							event.finish();
							return;
						}
					}
					if(event.draw){
						game.delay(0,300);
						player.$draw(card);
					}
					"step 2"
					if(card.clone){
						game.broadcast(function(card,player){
							if(card.clone){
								card.clone.moveDelete(player);
							}
						},card,player);
						card.clone.moveDelete(player);
						game.addVideo('gain2',player,get.cardsInfo([card.clone]));
					}
					player.equiping=true;
					"step 3"
					var info=get.info(card,false);
					var next=game.createEvent('replaceEquip');
					next.player=player;
					next.card=card;
					next.setContent(info.replaceEquip||'replaceEquip');
					"step 4"
					var info=get.info(card,false);
					if(get.itemtype(result)=='cards'){
						player.lose(result,false,'visible').set('type','equip').set('getlx',false).swapEquip=true;
						if(info.loseThrow){
							player.$throw(result,1000);
						}
						event.swapped=true;
					}
					"step 5"
					//if(player.isMin() || player.countCards('e',{subtype:get.subtype(card)})){
					if(player.isMin()||!player.canEquip(card)){
						event.finish();
						game.cardsDiscard(card);
						delete player.equiping;
						return;
					}
					var subtype=get.subtype(card);
					if(subtype=='equip6') subtype='equip3';
					game.broadcastAll(function(type){
						if(lib.config.background_audio){
							game.playAudio('effect',type);
						}
					},subtype);
					player.$equip(card);
					game.addVideo('equip',player,get.cardInfo(card));
					if(event.log!=false) game.log(player,'装备了',card);
					if(event.updatePile) game.updateRoundNumber();
					"step 6"
					var info=get.info(card,false);
					if(info.onEquip&&(!info.filterEquip||info.filterEquip(card,player))){
						if(Array.isArray(info.onEquip)){
							for(var i=0;i<info.onEquip.length;i++){
								var next=game.createEvent('equip_'+card.name);
								next.setContent(info.onEquip[i]);
								next.player=player;
								next.card=card;
							}
						}
						else{
							var next=game.createEvent('equip_'+card.name);
							next.setContent(info.onEquip);
							next.player=player;
							next.card=card;
						}
						if(info.equipDelay!=false) game.delayx();
					}
					delete player.equiping;
					if(event.delay){
						game.delayx();
					}
				},
				//装备栏 END
				changeGroup:function(){
					'step 0'
					event.originGroup=player.group;
					if(!event.group) event.group=player.group;
					var group=event.group;
					player.getHistory('custom').push(event);
					if(event.broadcast!==false){
						game.broadcast(function(player,group){
							player.group=group;
							player.node.name.dataset.nature=get.groupnature(group);
						},player,group);
					}
					player.group=group;
					player.node.name.dataset.nature=get.groupnature(group);
					if(event.log!==false) game.log(player,'将势力变为了','#y'+get.translation(group+2));
				},
				chooseToDebate:function(){
					'step 0'
					event.targets=event.list.filter(function(i){
						return i.countCards('h')>0;
					});
					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<event.targets.length;i++){
						var card=result[i].cards[0],target=event.targets[i];
						if(get.color(card,target)=='red') red.push([target,card]);
						else black.push([target,card]);
					}
					event.red=red; event.black=black;
					if(red.length){
						game.log(red.map(function(i){
							return i[0];
						}),'意见为<span class="firetext">红色</span>,展示了',red.map(function(i){
							return i[1];
						}));
					}
					else game.log('#b无人','意见为<span class="firetext">红色</span>');
					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.length;i++){
							dialog.add('<div class="text center">'+list[i]+'</div>');
							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;i<redArgs.length;i++){
							var list=redArgs[i];
							var button=ui.create.button(list[1],'card',dialog.buttonss[0]);
							button.querySelector('.info').innerHTML=func(list[0]);
						}
						for(var i=0;i<blackArgs.length;i++){
							var list=blackArgs[i];
							var button=ui.create.button(list[1],'card',dialog.buttonss[1]);
							button.querySelector('.info').innerHTML=func(list[0]);
						}
						dialog.open();
					},get.translation(player),event.videoId,red,black);
					game.delay(4);
					'step 2'
					game.broadcastAll('closeDialog',event.videoId);
					var opinion=null;
					if(event.red.length>event.black.length) opinion='red';
					else if(event.red.length<event.black.length) opinion='black';
					if(opinion) game.log(player,'本次发起的议事结果为',opinion=='red'?'<span class="firetext">红色</span>':'#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+='<br>(点击屏幕可以跳过等待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('<div class="text center">'+(beatmap.prompt||'在音符滑条和底部判定区重合时点击屏幕!')+'</div>');
						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='<div class="text center">演奏结束!<br>最大连击数:'+max_combo+'  精准度:'+acc+'%</div>';
							game.me.$fullscreenpop('<span style="font-family:xinwei">演奏评级:<span data-nature="'+rank[1]+'">'+rank[0]+'</span></span>',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<range1[0]) return;
								nodes.remove(node);
								clearTimeout(node.timeout);
								node.style.transform='';
								node.style.transition='all 0s';
								node.style.top=(height*((top-10)/100))+'px';
								ui.refresh(node);
								node.style.transition='all 0.5s';
								node.style.transform='scale(1.2)';
								node.delete();
								if(top>=range3[0]&&top<range3[1]){
									score+=5;
									player.popup('Perfect','orange',false);
								}
								else if(top>=range2[0]&&top<range2[1]){
									score+=3;
									player.popup('Great','wood',false);
								}
								else{
									score+=1;
									player.popup('Good','soil',false);
								}
								if(player.damagepopups.length) player.$damagepop();
								combo++;
								max_combo=Math.max(combo,max_combo);
								hitsound_audio.currentTime=0;
								if(hitsound_audio.paused) Promise.resolve(hitsound_audio.play()).catch(()=>void 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=('<div class="text center">'+i.textPrompt(event.moved[i._link])+'</div>');
							}
							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.length;i++){
							var tex=event.dialog.add('<div class="text center">'+list[i][0]+'</div>');
							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('<div class="text center">点击两张牌以交换位置;点击一张牌并点击其他区域以移动卡牌</div>');
						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;i<targets.length;i++){
								if(event.filterTarget){
									if(!event.filterTarget(card,player,targets[i])){
										targets.splice(i--,1);
									}
								}
								else if(!player.canUse(card,targets[i],event.nodistance?false:null,event.addCount===false?null:true)){
									targets.splice(i--,1);
								}
							}
							if(targets.length){
								event.targets2=targets;
							}
							else{
								event.finish();
								return;
							}
						}
						else event.targets2=[];
						if(event.forced){
							event._result={bool:true};
							return;
						}
						else{
							var next=player.chooseBool();
							next.set('prompt',event.prompt||('是否'+(event.targets2.length?'对':'')+get.translation(event.targets2)+'使用'+get.translation(card)+'?'));
							if(event.hsskill) next.setHiddenSkill(event.hsskill);
							if(event.prompt2) next.set('prompt2',event.prompt2);
							next.ai=function(){
								var eff=0;
								for(var i=0;i<event.targets2.length;i++){
									eff+=get.effect(event.targets2[i],card,player,player);
								}
								return eff>0;
							};
						}
					}
					else{
						if(event.filterTarget){
							var targets=game.filterPlayer(function(current){
								return event.filterTarget(card,player,current);
							});
							if(targets.length<range[0]){
								event._result={bool:false};
								return;
							}
							else if(!info.complexTarget&&targets.length==range[0]&&range[0]==range[1]){
								event.targets2=targets;
								event._result={bool:true};
								return;
							}
						}
						var next=player.chooseTarget();
						next.set('_get_card',card);
						next.set('filterTarget',event.filterTarget||function(card,player,target){
							if(!_status.event.targets.contains(target)) return false;
							if(!_status.event.nodistance&&!lib.filter.targetInRange(card,player,target)) return false;
							return lib.filter.targetEnabledx(card,player,target);
						});
						next.set('ai',event.ai||get.effect_use);
						next.set('selectTarget',event.selectTarget||lib.filter.selectTarget);
						if(event.nodistance) next.set('nodistance',true);
						if(event.forced) next.set('forced',true);
						if(event.addCount!==false) next.set('addCount_extra',true);
						next.set('targets',targets);
						next.set('prompt',event.prompt||('选择'+get.translation(card)+'的目标'));
						if(event.prompt2) next.set('prompt2',event.prompt2);
						if(event.hsskill) next.setHiddenSkill(event.hsskill);
					}
					'step 1'
					if(result.bool){
						event.result={
							bool:true,
							targets:event.targets2||result.targets,
						};
						var next=player.useCard(card,event.targets2||result.targets);
						next.oncard=event.oncard;
						if(cards) next.cards=cards.slice(0);
						if(event.nopopup) next.nopopup=true;
						if(event.animate===false) next.animate=false;
						if(event.throw===false) next.throw=false;
						if(event.addCount===false) next.addCount=false;
						if(event.noTargetDelay) next.targetDelay=false;
						if(event.nodelayx) next.delayx=false;
						if(event.logSkill){
							if(typeof event.logSkill=='string'){
								next.skill=event.logSkill;
							}
							else if(Array.isArray(event.logSkill)){
								player.logSkill.apply(player,event.logSkill);
							}
						}
					}
					else event.result={bool:false};
				},
				chooseToDuiben:function(){
					'step 0'
					if(!event.namelist) event.namelist=['全军出击','分兵围城','奇袭粮道','开城诱敌'];
					game.broadcastAll(function(list){
						var list2=['db_atk1','db_atk2','db_def1','db_def2'];
						for(var i=0;i<4;i++){
							lib.card[list2[i]].image='card/'+list2[i]+(list[0]=='全军出击'?'':'_'+list[i]);
							lib.translate[list2[i]]=list[i];
						}
					},event.namelist);
					if(!event.title) event.title='对策';
					game.log(player,'向',target,'发起了','#y'+event.title);
					if(!event.ai) event.ai=function(){return 1+Math.random()};
					if(_status.connectMode){
						player.chooseButtonOL([
							[player,[event.title+':请选择一种策略',[[['','','db_def2'],['','','db_def1']],'vcard']],true],
							[target,[event.title+':请选择一种策略',[[['','','db_atk1'],['','','db_atk2']],'vcard']],true]
						],function(){},event.ai).set('switchToAuto',function(){
							_status.event.result='ai';
						}).set('processAI',function(){
							var buttons=_status.event.dialog.buttons;
							return {
								bool:true,
								links:[buttons.randomGet().link],
							}
						});
					}
					'step 1'
					if(_status.connectMode){
						event.mes=result[player.playerid].links[0][2];
						event.tes=result[target.playerid].links[0][2];
						event.goto(4);
					}
					else{
						player.chooseButton([event.title+':请选择一种策略',[[['','','db_def2'],['','','db_def1']],'vcard']],true).ai=event.ai;
					}
					'step 2'
					event.mes=result.links[0][2];
					target.chooseButton([event.title+':请选择一种策略',[[['','','db_atk1'],['','','db_atk2']],'vcard']],true).ai=event.ai;
					'step 3'
					event.tes=result.links[0][2];
					'step 4'
					game.broadcast(function(){
						ui.arena.classList.add('thrownhighlight');
					});
					ui.arena.classList.add('thrownhighlight');
					game.addVideo('thrownhighlight1');
					target.$compare(game.createCard(event.tes,'',''),player,game.createCard(event.mes,'',''));
					game.log(target,'选择的策略为','#g'+get.translation(event.tes));
					game.log(player,'选择的策略为','#g'+get.translation(event.mes));
					game.delay(0,1500);
					'step 5'
					var mes=event.mes.slice(6);
					var tes=event.tes.slice(6);
					var str;
					if(mes==tes){
						str=get.translation(player)+event.title+'成功';
						player.popup('胜','wood');
						target.popup('负','fire');
						game.log(player,'#g胜');
						event.result={bool:true};
					}
					else{
						str=get.translation(player)+event.title+'失败';
						target.popup('胜','wood');
						player.popup('负','fire');
						game.log(target,'#g胜');
						event.result={bool:false};
					}
					event.result.player=event.mes;
					event.result.target=event.tes;
					game.broadcastAll(function(str){
						var dialog=ui.create.dialog(str);
						dialog.classList.add('center');
						setTimeout(function(){
							dialog.close();
						},1000);
					},str);
					game.trySkillAudio(event.getParent().name+'_'+(event.result.bool?'true'+mes:'false'),player);
					game.delay(2);
					'step 6'
					game.broadcastAll(function(){
						ui.arena.classList.remove('thrownhighlight');
					});
					game.addVideo('thrownhighlight2');
					if(event.clear!==false){
						game.broadcastAll(ui.clear);
					}
				},
				chooseToPSS:function(){
					'step 0'
					game.log(player,'对',target,'发起了猜拳');
					if(_status.connectMode){
						player.chooseButtonOL([
							[player,['猜拳:请选择一种手势',[[['','','pss_stone'],['','','pss_scissor'],['','','pss_paper']],'vcard']],true],
							[target,['猜拳:请选择一种手势',[[['','','pss_stone'],['','','pss_scissor'],['','','pss_paper']],'vcard']],true]
						],function(){},function(){return 1+Math.random()}).set('switchToAuto',function(){
							_status.event.result='ai';
						}).set('processAI',function(){
							var buttons=_status.event.dialog.buttons;
							return {
								bool:true,
								links:[buttons.randomGet().link],
							}
						});
					}
					'step 1'
					if(_status.connectMode){
						event.mes=result[player.playerid].links[0][2];
						event.tes=result[target.playerid].links[0][2];
						event.goto(4);
					}
					else{
						player.chooseButton(['猜拳:请选择一种手势',[[['','','pss_stone'],['','','pss_scissor'],['','','pss_paper']],'vcard']],true).ai=function(){return 1+Math.random()};
					}
					'step 2'
					event.mes=result.links[0][2];
					target.chooseButton(['猜拳:请选择一种手势',[[['','','pss_stone'],['','','pss_scissor'],['','','pss_paper']],'vcard']],true).ai=function(){return 1+Math.random()};
					'step 3'
					event.tes=result.links[0][2];
					'step 4'
					game.broadcast(function(){
						ui.arena.classList.add('thrownhighlight');
					});
					ui.arena.classList.add('thrownhighlight');
					game.addVideo('thrownhighlight1');
					player.$compare(game.createCard(event.mes,'',''),target,game.createCard(event.tes,'',''));
					game.log(player,'选择的手势为','#g'+get.translation(event.mes));
					game.log(target,'选择的手势为','#g'+get.translation(event.tes));
					game.delay(0,1500);
					'step 5'
					var mes=event.mes.slice(4);
					var tes=event.tes.slice(4);
					var str;
					if(mes==tes){
						str='二人平局';
						player.popup('平','metal');
						target.popup('平','metal');
						game.log('猜拳的结果为','#g平局');
						event.result={tie:true};
					}
					else{
						if({paper:'stone',scissor:'paper',stone:'scissor'}[mes]==tes){
							str=get.translation(player)+'胜利';
							player.popup('胜','wood');
							target.popup('负','fire');
							game.log(player,'#g胜');
							event.result={bool:true};
						}
						else{
							str=get.translation(target)+'胜利';
							target.popup('胜','wood');
							player.popup('负','fire');
							game.log(target,'#g胜');
							event.result={bool:false};
						}
					}
					game.broadcastAll(function(str){
						var dialog=ui.create.dialog(str);
						dialog.classList.add('center');
						setTimeout(function(){
							dialog.close();
						},1000);
					},str);
					game.delay(2);
					'step 6'
					game.broadcastAll(function(){
						ui.arena.classList.remove('thrownhighlight');
					});
					game.addVideo('thrownhighlight2');
					if(event.clear!==false){
						game.broadcastAll(ui.clear);
					}
				},
				cardsDiscard:function(){
					game.getGlobalHistory().cardMove.push(event);
					var withPile=false;
					for(var i=0;i<cards.length;i++){
						if(get.position(cards[i],true)=='c') withPile=true;
						cards[i].discard();
					}
					if(withPile) game.updateRoundNumber();
				},
				orderingDiscard:function(){
					var cards=event.relatedEvent.orderingCards.slice(0);
					for(var i=0;i<cards.length;i++){
						if(get.position(cards[i],true)!='o') cards.splice(i--,1);
					}
					if(cards.length) game.cardsDiscard(cards);
				},
				cardsGotoOrdering:function(){
					game.getGlobalHistory().cardMove.push(event);
					var withPile=false;
					for(var i=0;i<cards.length;i++){
						if(get.position(cards[i],true)=='c') withPile=true;
						cards[i].fix();
						ui.ordering.appendChild(cards[i]);
					}
					if(withPile) game.updateRoundNumber();
					var evt=event.relatedEvent||event.getParent();
					if(!evt.orderingCards) evt.orderingCards=[];
					if(!evt.noOrdering&&!evt.cardsOrdered){
						evt.cardsOrdered=true;
						var next=game.createEvent('orderingDiscard',false,evt.getParent());
						next.relatedEvent=evt;
						next.setContent('orderingDiscard');
					}
					if(!evt.noOrdering) evt.orderingCards.addArray(cards);
				},
				cardsGotoSpecial:function(){
					game.getGlobalHistory().cardMove.push(event);
					var withPile=false;
					for(var i=0;i<cards.length;i++){
						if(get.position(cards[i],true)=='c') withPile=true;
						cards[i].fix();
						ui.special.appendChild(cards[i]);
					}
					if(withPile) game.updateRoundNumber();
					if(event.toRenku){
						_status.renku.addArray(cards);
						if(_status.renku.length>6){
							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;i<lib.onwash.length;i++){
							if(lib.onwash[i]()=='remove'){
								lib.onwash.splice(i--,1);
							}
						}
					}
					game.getGlobalHistory().cardMove.push(event);
					if(!event._triggeronly) game.$cardsGotoPile(event);
				},
				chooseToEnable:function(){
					'step 0'
					var list=[];
					for(var i=1;i<=5;i++){
						if(player.hasDisabledSlot(i))  list.push('equip'+i);
					}
					if(!list.length) event.finish();
					else if(list.length==1){
						event.list=list;
						event._result={control:list[0]};
					}
					else{
						var next=player.chooseControl(list);
						next.set('prompt','请选择恢复一个装备栏');
						if(!event.ai) event.ai=function(event,player,list){
							return list.randomGet();
						}
						event.ai=event.ai(event.getParent(),player,list);
						next.ai=function(){
							return event.ai;
						};
					}
					'step 1'
					event.result={control:result.control};
					player.enableEquip(result.control);
				},
				chooseToDisable:function(){
					'step 0'
					var list=[];
					for(var i=1;i<=5;i++){
						if(player.hasEnabledSlot(i)) list.push('equip'+i);
					}
					if(event.horse){
						if(list.contains('equip3')&&list.contains('equip4')) list.push('equip3_4');
						list.remove('equip3');
						list.remove('equip4');
					}
					if(!list.length) event.finish();
					else if(list.length==1){
						event.list=list;
						event._result={control:list[0]};
					}
					else{
						list.sort();
						event.list=list;
						var next=player.chooseControl(list);
						next.set('prompt','请选择废除一个装备栏');
						if(!event.ai) event.ai=function(event,player,list){
							return list.randomGet();
						}
						event.ai=event.ai(event.getParent(),player,list);
						next.ai=function(){
							return event.ai;
						};
					}
					'step 1'
					event.result={control:result.control};
					if(result.control=='equip3_4'){
						player.disableEquip(3,4);
					}
					else player.disableEquip(result.control);
				},
				swapEquip:function(){
					"step 0"
					game.log(player,'和',target,'交换了装备区中的牌')
					event.cards=[player.getCards('e'),target.getCards('e')];
					game.loseAsync({
						player:player,
						target:target,
						cards1:event.cards[0],
						cards2:event.cards[1],
					}).setContent('swapHandcardsx');
					"step 1"
					for(var i=0;i<event.cards[1].length;i++){
						if(get.position(event.cards[1][i],true)=='o') player.equip(event.cards[1][i]);
					}
					for(var i=0;i<event.cards[0].length;i++){
						if(get.position(event.cards[0][i],true)=='o') target.equip(event.cards[0][i]);
					}
				},
				disableJudge:function(){
					'step 0'
					game.log(player,'废除了判定区');
					var js=player.getCards('j');
					if(js.length) player.discard(js);
					player.storage._disableJudge=true;
					//player.markSkill('_disableJudge');
					'step 1'
					game.broadcastAll(function(player,card){
						player.$disableJudge();
					},player);
				},
				enableJudge:function(){
					if(!player.storage._disableJudge) return;
					game.log(player,'恢复了判定区');
					game.broadcastAll(function(player){
						player.$enableJudge();
					},player);
				},
				/*----分界线----*/
				phasing:function(){
					'step 0'
					while(ui.dialogs.length){
						ui.dialogs[0].close();
					}
					game.phaseNumber++;
					player.phaseNumber++;
					game.broadcastAll(function(player,player2,num,popup){
						if(lib.config.glow_phase){
							if(player2) player2.classList.remove('glow_phase');
							player.classList.add('glow_phase');
						}
						player.phaseNumber=num;
						if(popup&&lib.config.show_phase_prompt) player.popup('回合开始',null,false);
					},player,_status.currentPhase,player.phaseNumber,!player.noPhaseDelay);
					_status.currentPhase=player;
					_status.discarded=[];
					game.syncState();
					game.addVideo('phaseChange',player);
					if(game.phaseNumber==1){
						delete player._start_cards;
						if(lib.configOL.observe){
							lib.configOL.observeReady=true;
							game.send('server','config',lib.configOL);
						}
					}
					game.log();
					game.log(player,'的回合开始');
					player._noVibrate=true;
					if(get.config('identity_mode')!='zhong'&&get.config('identity_mode')!='purple'&&!_status.connectMode){
						var num;
						switch(get.config('auto_identity')){
							case 'one':num=1;break;
							case 'two':num=2;break;
							case 'three':num=3;break;
							case 'always':num=-1;break;
							default:num=0;break;
						}
						if(num&&!_status.identityShown&&game.phaseNumber>game.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.num<targets.length) event.goto(1);
				},
				reverseOrder:function(){
					"step 0"
					game.delay();
					"step 1"
					var choice;
					if(get.tag(card,'multineg')){
						choice=(player.previous.side==player.side)?'逆时针':'顺时针';
					}
					else{
						choice=(player.next.side==player.side)?'逆时针':'顺时针';
					}
					player.chooseControl('顺时针','逆时针',function(event,player){
						return _status.event.choice||'逆时针';
					}).set('prompt','选择'+get.translation(card)+'的结算方向').set('choice',choice).set('forceDie',true);
					"step 2"
					if(result&&result.control=='顺时针'){
						var evt=event.getParent(),sorter=(_status.currentPhase||player);
						evt.fixedSeat=true;
						evt.targets.sortBySeat(sorter);
						evt.targets.reverse();
						if(evt.targets[evt.targets.length-1]==sorter){
							evt.targets.unshift(evt.targets.pop());
						}
					}
				},
				addJudgeCard:function(){
					if(lib.filter.judge(card,player,target)&&cards.length&&get.position(cards[0],true)=='o') target.addJudge(card,cards);
				},
				equipCard:function(){
					if(cards.length&&get.position(cards[0],true)=='o') target.equip(cards[0]);
				},
				gameDraw:function(){
					"step 0"
					if(_status.brawl&&_status.brawl.noGameDraw){
						event.finish();
						return;
					}
					var end=player;
					var numx=num;
					do{
						if(typeof num=='function'){
							numx=num(player);
						}
						if(player.getTopCards) player.directgain(player.getTopCards(numx));
						else player.directgain(get.cards(numx));
						if(player.singleHp===true&&get.mode()!='guozhan'&&(lib.config.mode!='doudizhu'||_status.mode!='online')){
							player.doubleDraw();
						}
						player._start_cards=player.getCards('h');
						player=player.next;
					}
					while(player!=end);
					event.changeCard=get.config('change_card');
					if(_status.connectMode||(lib.config.mode=='doudizhu'&&_status.mode=='online')||lib.config.mode!='identity'&&lib.config.mode!='guozhan'&&lib.config.mode!='doudizhu'){
						event.changeCard='disabled';
					}
					"step 1"
					if(event.changeCard!='disabled'&&!_status.auto){
						event.dialog=ui.create.dialog('是否使用手气卡?');
						ui.create.confirm('oc');
						event.custom.replace.confirm=function(bool){
							_status.event.bool=bool;
							game.resume();
						}
					}
					else{
						event.finish();
					}
					"step 2"
					if(event.changeCard=='once'){
						event.changeCard='disabled';
					}
					else if(event.changeCard=='twice'){
						event.changeCard='once';
					}
					else if(event.changeCard=='disabled'){
						event.bool=false;
						return;
					}
					_status.imchoosing=true;
					event.switchToAuto=function(){
						_status.event.bool=false;
						game.resume();
					}
					game.pause();
					"step 3"
					_status.imchoosing=false;
					if(event.bool){
						if(game.changeCoin){
							game.changeCoin(-3);
						}
						var hs=game.me.getCards('h');
						game.addVideo('lose',game.me,[get.cardsInfo(hs),[],[],[]]);
						for(var i=0;i<hs.length;i++){
							hs[i].discard(false);
						}
						game.me.directgain(get.cards(hs.length));
						event.goto(2);
					}
					else{
						if(event.dialog) event.dialog.close();
						if(ui.confirm) ui.confirm.close();
						game.me._start_cards=game.me.getCards('h');
						event.finish();
					}
				},
				phaseLoop:function(){
					"step 0"
					var num=1,current=player;
					while(current.getSeatNum()==0){
						current.setSeatNum(num);
						current=current.next;
						num++;
					}
					"step 1"
					for(var i=0;i<lib.onphase.length;i++){
						lib.onphase[i]();
					}
					player.phase();
					"step 2"
					if(!game.players.contains(event.player.next)){
						event.player=game.findNext(event.player.next);
					}
					else{
						event.player=event.player.next;
					}
					event.goto(1);
				},
				loadPackage:function(){
					'step 0'
					if(event.packages.length){
						window.game=game;
						var pack=event.packages.shift().split('/');
						lib.init.js(lib.assetURL+pack[0],pack[1],game.resume);
						game.pause();
					}
					else{
						event.finish();
					}
					'step 1'
					if(!lib.config.dev) delete window.game;
					var character=lib.imported.character;
					var card=lib.imported.card;
					var i,j,k;
					for(i in character){
						if(character[i].character){
							var characterPack=lib.characterPack[i];
							if(characterPack) Object.assign(characterPack,character[i].character);
							else lib.characterPack[i]=character[i].character;
						}
						if(character[i].forbid&&character[i].forbid.contains(lib.config.mode)) continue;
						if(character[i].mode&&character[i].mode.contains(lib.config.mode)==false) continue;

						if(Array.isArray(lib[j])&&Array.isArray(character[i][j])){
							lib[j].addArray(character[i][j]);
							continue;
						}
						for(j in character[i]){
							if(j=='mode'||j=='forbid'||j=='characterSort') 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<character[i][j][k][3].length;l++){
										lib.skilllist.add(character[i][j][k][3][l]);
									}
								}
								if(j=='translate'&&k==i){
									lib[j][k+'_character_config']=character[i][j][k];
								}
								else{
									if(lib[j][k]==undefined){
										Object.defineProperty(lib[j],k,Object.getOwnPropertyDescriptor(character[i][j],k));
									}
									else if(Array.isArray(lib[j][k])&&Array.isArray(character[i][j][k])){
										lib[j][k].addArray(character[i][j][k]);
									}
									else{
										console.log(
											`dublicate ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`,
											lib[j][k],
											`\ncharacter.${i}.${j}.${k}`,
											character[i][j][k]
										);
									}
								}
							}
						}
					}
					for(i in card){
						var cardPack=lib.cardPack[i]?lib.cardPack[i]:lib.cardPack[i]=[];
						if(card[i].card){
							for(var j in card[i].card){
								if(!card[i].card[j].hidden&&card[i].translate[j+'_info']){
									cardPack.push(j);
								}
							}
						}
						for(j in card[i]){
							if(j=='mode'||j=='forbid') continue;
							if(j=='list') continue;
							for(k in card[i][j]){
								if(j=='skill'&&k[0]=='_'&&!lib.config.cards.contains(i)){
									continue;
								}
								if(j=='translate'&&k==i){
									lib[j][k+'_card_config']=card[i][j][k];
								}
								else{
									if(lib[j][k]==undefined) Object.defineProperty(lib[j],k,Object.getOwnPropertyDescriptor(card[i][j],k));
									else{
										console.log(
											`dublicate ${j} in card ${i}:\n${k}\nlib.${j}.${k}`,
											lib[j][k],
											`\ncard.${i}.${j}.${k}`,
											card[i][j][k]
										);
									}
								}
							}
						}
					}
					event.goto(0);
				},
				loadMode:function(){
					'step 0'
					window.game=game;
					lib.init.js(lib.assetURL+'mode',event.mode,game.resume);
					game.pause();
					'step 1'
					if(!lib.config.dev) delete window.game;
					event.result=lib.imported.mode[event.mode];
					delete lib.imported.mode[event.mode];
				},
				forceOver:function(){
					'step 0'
					while(ui.controls.length){
						ui.controls[0].close();
					}
					while(ui.dialogs.length){
						ui.dialogs[0].close();
					}
					'step 1'
					if(event.bool!='noover'){
						game.over(event.bool);
					}
					if(event.callback){
						event.callback();
					}
				},
				arrangeTrigger:function(){
					'step 0'
					event.filter1=function(info){
						if(info[1].isDead()&&!lib.skill[info[0]].forceDie) return false;
						if(info[1].isOut()&&!lib.skill[info[0]].forceOut) return false;
						return lib.filter.filterTrigger(trigger,info[1],event.triggername,info[0]);
					}
					event.filter2=function(info2){
						var info=lib.skill[info2[0]];
						if(!lib.translate[info2[0]]||info.silent) return false;
						return true;
					}
					event.filter3=function(info,info2){
						return event.filter2(info2)&&event.filter1(info2)&&info2[1]==info[1]&&info[2]==info2[2]&&(lib.skill.global.contains(info2[0])||info[1].hasSkill(info2[0],true));
					}
					'step 1'
					if(trigger.filterStop&&trigger.filterStop()){
						event.finish();
					}
					else if(event.list.length){
						var info=event.list.shift();
						game.createTrigger(event.triggername,info[0],info[1],trigger);
						event.redo();
					}
					'step 2'
					if(!event.map.length){
						if(event.list2.length){
							var info=event.list2.shift();
							game.createTrigger(event.triggername,info[0],info[1],trigger);
							event.redo();
						}
						else{
							if(trigger._triggering==this){
								delete trigger._triggering;
							}
							event.finish();
							return;
						}
					};
					event.doing=event.map.shift();
					'step 3'
					event.num=0;
					var bool=false;
					var list=event.doing.list;
					for(var i=0;i<list.length;i++){
						if(event.filter1(list[i])){
							event.num=i;
							bool=true;
							break;
						}
					}
					if(!bool){event.goto(2);return;}
					var priority=list[event.num][2];
					for(var i=0;i<event.num;i++){
						if(event.doing.list[i][2]>priority){
							event.doing.list.splice(i--,1);
							event.num--;
						}
					}
					event.choice=[];
					if(event.num<event.doing.list.length-1&&event.filter2(event.doing.list[event.num])){
						var current=event.doing.list[event.num];
						event.choice.push(current);
						for(var i=event.num+1;i<event.doing.list.length;i++){
							if(event.filter3(current,event.doing.list[i])) event.choice.push(event.doing.list[i]);
						}
					}
					if(event.choice.length<2) event.goto(6);
					'step 4'
					var controls=[];
					event.current=event.choice[0][1]
					for(var i=0;i<event.choice.length;i++){
						controls.push(event.choice[i][0]);
					}
					event.current.chooseControl(controls)
					.set('prompt','选择下一个触发的技能').set('forceDie',true).set('arrangeSkill',true).set('includeOut',true)
					'step 5'
					if(result.control){
						for(var i=0;i<event.doing.list.length;i++){
							if(event.doing.list[i][0]==result.control&&event.doing.list[i][1]==event.current){
								event.num=i;break;
							}
						}
					}
					'step 6'
					var info=event.doing.list[event.num];
					if(info){
						event.doing.list2.push(info);
						event.doing.list.splice(event.num,1);
						game.createTrigger(event.triggername,info[0],info[1],trigger);
					}
					'step 7'
					if(trigger.filterStop&&trigger.filterStop()){
						event.finish();
					}
					else event.goto(event.doing.list.length?3:2);
				},
				createTrigger:function(){
					"step 0"
					//console.log('triggering: ' + player.name+ ' \'s skill: ' + event.skill+' in ' + event.triggername)
					if(lib.filter.filterTrigger(trigger,player,event.triggername,event.skill)){
						var fullskills=game.expandSkills(player.getSkills().concat(lib.skill.global));
						if(!fullskills.contains(event.skill)){
							var info=get.info(event.skill);
							var hidden=player.hiddenSkills.slice(0);
							var invisible=player.invisibleSkills.slice(0);
							game.expandSkills(hidden);
							game.expandSkills(invisible);
							if(hidden.contains(event.skill)){
								if(!info.silent&&player.hasSkillTag('nomingzhi',false,null,true)){
									event.finish();
								}
								else if(!info.direct){
									event.trigger('triggerHidden');
								}
								else{
									event.skillHidden=true;
								}
							}
							else if(invisible.contains(event.skill)){
								event.trigger('triggerInvisible');
							}
							else{
								var keep=false;
								for(var i in player.additionalSkills){
									if(i.startsWith('hidden:')&&game.expandSkills(player.additionalSkills[i]).contains(event.skill)){
										keep=true;break;
									}
								}
								if(!keep){
									event.finish();
								}
							}
						}
					}
					else{
						event.finish();
					}
					"step 1"
					if(event.cancelled){
						event.finish();
						return;
					}
					var info=get.info(event.skill);
					if(!event.revealed&&!info.forced){
						var checkFrequent=function(info){
							if(player.hasSkillTag('nofrequent',false,event.skill)) return false;
							if(typeof info.frequent=='boolean') return info.frequent;
							if(typeof info.frequent=='function') return info.frequent(trigger,player);
							if(info.frequent=='check'&&typeof info.check=='function') return info.check(trigger,player);
							return false;
						}
						if(info.direct&&player.isUnderControl()){
							game.swapPlayerAuto(player);
							event._result={bool:true};
							event._direct=true;
						}
						else if(info.direct){
							event._result={bool:true};
							event._direct=true;
						}
						else if(info.direct&&player.isOnline()){
							event._result={bool:true};
							event._direct=true;
						}
						else{
							if(checkFrequent(info)){
								event.frequentSkill=true;
							}
							var str;
							var check=info.check;
							if(info.prompt) str=info.prompt;
							else{
								if(typeof info.logTarget=='string'){
									str=get.prompt(event.skill,trigger[info.logTarget],player);
								}
								else if(typeof info.logTarget=='function'){
									var logTarget=info.logTarget(trigger,player);
									if(get.itemtype(logTarget).startsWith('player')) str=get.prompt(event.skill,logTarget,player);
								}
								else{
									str=get.prompt(event.skill,null,player);
								}
							}
							if(typeof str=='function'){str=str(trigger,player)}
							var next=player.chooseBool(str);
							if(event.frequentSkill) next.set('frequentSkill',event.skill);
							next.set('forceDie',true);
							next.set('includeOut',true);
							next.ai=function(){
								return !check||check(trigger,player);
							};
							if(typeof info.prompt2=='function'){
								next.set('prompt2',info.prompt2(trigger,player));
							}
							else if(typeof info.prompt2=='string'){
								next.set('prompt2',info.prompt2);
							}
							else if(info.prompt2!=false){
								if(lib.dynamicTranslate[event.skill]) next.set('prompt2',lib.dynamicTranslate[event.skill](player,event.skill));
								else if(lib.translate[event.skill+'_info']) next.set('prompt2',lib.translate[event.skill+'_info']);
							}
							if(trigger.skillwarn){
								if(next.prompt2){
									next.set('prompt2','<span class="thundertext">'+trigger.skillwarn+'。</span>'+next.prompt2);
								}
								else{
									next.set('prompt2',trigger.skillwarn);
								}
							}
						}
					}
					"step 2"
					var info=get.info(event.skill);
					if(result&&result.bool!=false){
						var autodelay=info.autodelay;
						if(typeof autodelay=='function'){
							autodelay=autodelay(trigger,player);
						}
						if(autodelay&&(info.forced||!event.isMine())){
							if(typeof autodelay=='number'){
								game.delayx(autodelay);
							}
							else{
								game.delayx();
							}
						}
					}
					"step 3"
					var info=get.info(event.skill);
					if(result&&result.bool==false){
						if(info.oncancel) info.oncancel(trigger,player);
						event.finish();
						return;
					}
					if(info.popup!=false&&!info.direct){
						if(info.popup){
							player.popup(info.popup);
							game.log(player,'发动了','【'+get.skillTranslation(event.skill,player)+'】');
						}
						else{
							if(info.logTarget&&info.logLine!==false){
								if(typeof info.logTarget=='string'){
									player.logSkill(event.skill,trigger[info.logTarget],info.line);
								}
								else if(typeof info.logTarget=='function'){
									player.logSkill(event.skill,info.logTarget(trigger,player),info.line);
								}
							}
							else{
								player.logSkill(event.skill,false,info.line);
							}
						}
					}
					var next=game.createEvent(event.skill);
					if(typeof info.usable=='number'){
						player.addSkill('counttrigger');
						if(!player.storage.counttrigger){
							player.storage.counttrigger={};
						}
						if(!player.storage.counttrigger[event.skill]){
							player.storage.counttrigger[event.skill]=1;
						}
						else{
							player.storage.counttrigger[event.skill]++;
						}
					}
					next.player=player;
					next._trigger=trigger;
					next.triggername=event.triggername;
					next.setContent(info.content);
					next.skillHidden=event.skillHidden;
					if(info.forceDie) next.forceDie=true;
					if(info.forceOut) next.includeOut=true;
					"step 4"
					if(player._hookTrigger){
						for(var i=0;i<player._hookTrigger.length;i++){
							var info=lib.skill[player._hookTrigger[i]].hookTrigger;
							if(info){
								if(info.after&&info.after(event,player,event.triggername)){
									event.trigger('triggerAfter');
									break;
								}
							}
						}
					}
				},
				playVideoContent:function(){
					'step 0'
					game.delay(0,500);
					'step 1'
					if(!game.chess){
						ui.control.innerHTML='';
						var nodes=[];
						for(var i=0;i<ui.arena.childNodes.length;i++){
							nodes.push(ui.arena.childNodes[i]);
						}
						for(var i=0;i<nodes.length;i++){
							if(nodes[i]==ui.canvas) continue;
							if(nodes[i]==ui.control) continue;
							if(nodes[i]==ui.mebg) continue;
							if(nodes[i]==ui.me) continue;
							if(nodes[i]==ui.roundmenu) continue;
							nodes[i].remove();
						}
						ui.sidebar.innerHTML='';
						ui.cardPile.innerHTML='';
						ui.discardPile.innerHTML='';
						ui.special.innerHTML='';
						ui.ordering.innerHTML='';
					}
					ui.system.firstChild.innerHTML='';
					ui.system.lastChild.innerHTML='';
					ui.system.firstChild.appendChild(ui.config2);
					if(ui.updateVideoMenu){
						ui.updateVideoMenu();
					}
					_status.videoDuration=1;
					ui.create.system('返回',function(){
						var mode=localStorage.getItem(lib.configprefix+'playbackmode');
						if(mode){
							game.saveConfig('mode',mode);
						}
						game.reload();
					});
					ui.create.system('重播',function(){
						_status.replayvideo=true;
						game.playVideo(_status.playback,lib.config.mode);
					});
					ui.create.system('暂停',ui.click.pause,true).id='pausebutton';
					var slow=ui.create.system('减速',function(){
						_status.videoDuration*=1.5;
						updateDuration();
					},true);
					var fast=ui.create.system('加速',function(){
						_status.videoDuration/=1.5;
						updateDuration();
					},true);
					var updateDuration=function(){
						if(_status.videoDuration>1){
							slow.classList.add('glow');
						}
						else{
							slow.classList.remove('glow');
						}
						if(_status.videoDuration<1){
							fast.classList.add('glow');
						}
						else{
							fast.classList.remove('glow');
						}
					}
					ui.system.style.display='';
					ui.refresh(ui.system);
					ui.system.show();
					ui.window.show();
					if(lib.config.mode!='versus'&&lib.config.mode!='boss'){
						ui.arena.style.display='';
						ui.refresh(ui.arena);
						ui.arena.show();
					}
					if(!game.chess){
						game.playerMap={};
					}
					game.finishCards();
					'step 2'
					if(event.video.length){
						var content=event.video.shift();
						// console.log(content);
						if(content.type=='delay'){
							game.delay(content.content);
						}
						else if(content.type=='play'){
							window.play={};
							if(!event.playtoload){
								event.playtoload=1;
							}
							else{
								event.playtoload++;
							}
							var script=lib.init.js(lib.assetURL+'play',content.name);
							script.addEventListener('load',function(){
								var play=window.play[content.name]
								if(play&&play.video){
									play.video(content.init);
								}
								event.playtoload--;
								if(event.playtoload==0){
									delete window.play;
								}
							});
						}
						else if(typeof content.player=='string'&&game.playerMap[content.player]&&
							game.playerMap[content.player].classList&&
							!game.playerMap[content.player].classList.contains('obstacle')){
							game.videoContent[content.type](game.playerMap[content.player],content.content);
						}
						else{
							game.videoContent[content.type](content.content);
						}
						if(event.video.length){
							game.delay(0,_status.videoDuration*Math.min(2000,event.video[0].delay));
						}
						event.redo();
					}
					else{
						_status.over=true;
						ui.system.lastChild.hide();
						setTimeout(function(){
							ui.system.lastChild.innerHTML='';
						},500);
					}
				},
				waitForPlayer:function(){
					'step 0'
					ui.auto.hide();
					ui.pause.hide();

					game.createServer();
					if(!lib.translate.zhu){
						lib.translate.zhu='主';
					}
					if(event.func){
						event.func();
					}
					if(!lib.configOL.number){
						lib.configOL.number=parseInt(lib.configOL.player_number);
					}
					if(game.onlineroom){
						game.send('server','config',lib.configOL);
					}

					ui.create.connectPlayers(game.ip);
					if(!window.isNonameServer){
						var me=game.connectPlayers[0];
						me.setIdentity('zhu');
						me.initOL(get.connectNickname(),lib.config.connect_avatar);
						me.playerid='1';
						game.onlinezhu='1';
					}
					_status.waitingForPlayer=true;
					if(window.isNonameServer){
						document.querySelector('#server_status').innerHTML='等待中';
					}
					game.pause();
					'step 1'
					_status.waitingForPlayer=false;
					lib.configOL.gameStarted=true;
					if(window.isNonameServer){
						document.querySelector('#server_status').innerHTML='游戏中';
					}
					if(game.onlineroom){
						game.send('server','config',lib.configOL);
					}
					for(var i=0;i<game.connectPlayers.length;i++){
						game.connectPlayers[i].delete();
					}
					delete game.connectPlayers;
					if(ui.roomInfo){
						ui.roomInfo.remove();
						delete ui.roomInfo;
					}
					if(ui.exitroom){
						ui.exitroom.remove();
						delete ui.exitroom;
					}
					game.broadcast('gameStart');
					game.delay(2);
					ui.auto.show();
					ui.pause.show();
					if(lib.config.show_cardpile){
						ui.cardPileButton.style.display='';
					}
				},
				replaceHandcards:function(){
					'step 0'
					if(event.players.contains(game.me)){
						game.me.chooseBool('是否置换手牌?');
					}
					else{
						event.finish();
					}
					'step 1'
					if(result&&result.bool){
						var hs=game.me.getCards('h')
						for(var i=0;i<hs.length;i++){
							hs[i].discard(false);
						}
						var cards=get.cards(hs.length);
						game.me._start_cards=cards;
						game.me.directgain(cards);
					}
				},
				replaceHandcardsOL:function(){
					'step 0'
					var send=function(){
						game.me.chooseBool('是否置换手牌?');
						game.resume();
					};
					var sendback=function(result,player){
						if(result&&result.bool){
							var hs=player.getCards('h')
							game.broadcastAll(function(player,hs){
								game.addVideo('lose',player,[get.cardsInfo(hs),[],[],[]]);
								for(var i=0;i<hs.length;i++){
									hs[i].discard(false);
								}
							},player,hs);
							var cards=get.cards(hs.length);
							player.directgain(cards);
							player._start_cards=cards;
						}
					};
					for(var i=0;i<event.players.length;i++){
						if(event.players[i].isOnline()){
							event.withol=true;
							event.players[i].send(send);
							event.players[i].wait(sendback);
						}
						else if(event.players[i]==game.me){
							event.withme=true;
							game.me.chooseBool('是否置换手牌?');
							game.me.wait(sendback);
						}
					}
					'step 1'
					if(event.withme){
						game.me.unwait(result);
					}
					'step 2'
					if(event.withol&&!event.resultOL){
						game.pause();
					}
				},
				phase:function(){
					'step 0'
					//初始化阶段列表
					if(!event.phaseList){
						event.phaseList=['phaseZhunbei','phaseJudge','phaseDraw','phaseUse','phaseDiscard','phaseJieshu'];
					}
					if(typeof event.num!='number'){
						event.num=0;
					}
					//规则集中的“回合开始后①”,更新游戏轮数,触发“一轮游戏开始时”
					var isRound=false;
					if(!event.skill){
						isRound=_status.roundSkipped;
						if(_status.isRoundFilter){
							isRound=_status.isRoundFilter(event,player);
						}
						else if(_status.seatNumSettled){
							var seatNum=player.getSeatNum();
							if(seatNum!=0){
								if(typeof _status.lastSeatNum!='number'||seatNum<_status.lastSeatNum) isRound=true;
								_status.lastSeatNum=seatNum;
							}
						}
						else if(player==_status.roundStart) isRound=true;
						if(isRound){
							delete _status.roundSkipped;
							game.roundNumber++;
							event._roundStart=true;
							game.updateRoundNumber();
							for(var i=0;i<game.players.length;i++){
								if(game.players[i].isOut()&&game.players[i].outCount>0){
									game.players[i].outCount--;
									if(game.players[i].outCount==0&&!game.players[i].outSkills){
										game.players[i].in();
									}
								}
							}
							event.trigger('roundStart');
						}
					}
					_status.globalHistory.push({
						cardMove:[],
						custom:[],
						useCard:[],
						changeHp:[],
						everything:[],
					});
					var players=game.players.slice(0).concat(game.dead);
					for(var i=0;i<players.length;i++){
						var current=players[i];
						current.actionHistory.push({useCard:[],respond:[],skipped:[],lose:[],gain:[],sourceDamage:[],damage:[],custom:[],useSkill:[]});
						current.stat.push({card:{},skill:{}});
						if(isRound){
							current.getHistory().isRound=true;
							current.getStat().isRound=true;
						}
					};
					if(isRound){
						game.getGlobalHistory().isRound=true;
					}
					'step 1'
					//规则集中的“回合开始后②(1v1武将登场专用)”
					event.trigger('phaseBeforeStart');
					'step 2'
					//规则集中的“回合开始后③(处理“游戏开始时”的时机)”
					event.trigger('phaseBefore');
					'step 3'
					//规则集中的“回合开始后④(卑弥呼〖纵傀〗的时机)”
					event.trigger('phaseBeforeEnd');
					'step 4'
					//规则集中的“回合开始后⑤”,进行翻面检测
					if(player.isTurnedOver()&&!event._noTurnOver){
						event.cancel();
						player.turnOver();
						player.phaseSkipped=true;
					}
					else{
						player.phaseSkipped=false;
						player.getHistory().isMe=true;
						player.getStat().isMe=true;
					}
					'step 5'
					//规则集中的“回合开始后⑥”,更新“当前回合角色”
					while(ui.dialogs.length){
						ui.dialogs[0].close();
					}
					game.phaseNumber++;
					player.phaseNumber++;
					game.broadcastAll(function(player,num,popup){
						if(lib.config.glow_phase){
							player.classList.add('glow_phase');
						}
						player.phaseNumber=num;
						if(popup&&lib.config.show_phase_prompt) player.popup('回合开始',null,false);
					},player,player.phaseNumber,!player.noPhaseDelay);
					_status.currentPhase=player;
					_status.discarded=[];
					game.syncState();
					game.addVideo('phaseChange',player);
					if(game.phaseNumber==1){
						delete player._start_cards;
						if(lib.configOL.observe){
							lib.configOL.observeReady=true;
							game.send('server','config',lib.configOL);
						}
					}
					game.log();
					game.log(player,'的回合开始');
					player._noVibrate=true;
					if(get.config('identity_mode')!='zhong'&&get.config('identity_mode')!='purple'&&!_status.connectMode){
						var num;
						switch(get.config('auto_identity')){
							case 'one':num=1;break;
							case 'two':num=2;break;
							case 'three':num=3;break;
							case 'always':num=-1;break;
							default:num=0;break;
						}
						if(num&&!_status.identityShown&&game.phaseNumber>game.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 6'
					//规则集中的“回合开始后⑦”,国战武将明置武将牌
					event.trigger('phaseBeginStart');
					'step 7'
					//规则集中的“回合开始后⑨”,进行当先,化身等操作
					//没有⑧ 因为⑧用不到
					event.trigger('phaseBegin');
					//阶段部分
					'step 8'
					if(player.isIn()&&num<event.phaseList.length){
						//规则集中没有的新时机 可以用来插入额外阶段啥的
						if(player.isIn()) event.trigger('phaseChange')
					}
					else event.goto(11);
					'step 9'
					if(player.isIn()&&num<event.phaseList.length){
						var phase=event.phaseList[num].split('|');
						event.currentPhase=phase[0];
						var next=player[event.currentPhase]();
						next.phaseIndex=num;
						if(phase.length>1){
							next._extraPhaseReason=phase[1];
						}
						if(event.currentPhase=='phaseDraw'||event.currentPhase=='phaseDiscard'){
							if(!player.noPhaseDelay){
								if(player==game.me){
									game.delay();
								}
								else{
									game.delayx();
								}
							}
						}
					}
					'step 10'
					if(event.currentPhase=='phaseUse'){
						game.broadcastAll(function(){
							if(ui.tempnowuxie){
								ui.tempnowuxie.close();
								delete ui.tempnowuxie;
							}
						});
						delete player._noSkill;
					}
					event.num++;
					'step 11'
					if(event.num<event.phaseList.length){
						event.goto(8);
					}
					else if(!event._phaseEndTriggered){
						event._phaseEndTriggered=true;
						event.trigger('phaseEnd');
						event.redo();
					}
					'step 12'
					event.trigger('phaseAfter');
					'step 13'
					//删除当前回合角色 此时处于“不属于任何角色的回合”的阶段
					game.broadcastAll(function(player){
						player.classList.remove('glow_phase');
						delete _status.currentPhase;
					},player);
				},
				/**
				 * @deprecated
				 */
				phase_old:function(){
					"step 0"
					player.phaseZhunbei();
					"step 1"
					player.phaseJudge();
					"step 2"
					player.phaseDraw();
					if(!player.noPhaseDelay){
						if(player==game.me){
							game.delay();
						}
						else{
							game.delayx();
						}
					}
					"step 3"
					player.phaseUse();
					"step 4"
					game.broadcastAll(function(){
						if(ui.tempnowuxie){
							ui.tempnowuxie.close();
							delete ui.tempnowuxie;
						}
					});
					player.phaseDiscard()
					if(!player.noPhaseDelay) game.delayx();
					//delete player.using;
					delete player._noSkill;
					"step 5"
					player.phaseJieshu();
				},
				phaseZhunbei:function(){
					event.trigger(event.name);
					game.log(player,'进入了准备阶段');
				},
				phaseJudge:function(){
					"step 0"
					game.log(player,'进入了判定阶段');
					event.cards=player.getCards('j');
					if(!event.cards.length) event.finish();
					"step 1"
					if(cards.length&&player.getCards('j').contains(cards[0])){
						event.card=cards.shift();
						if(event.card.classList.contains('removing')){
							event.card.remove();
							delete event.card;
							event.redo();
						}
						else if(event.card.classList.contains('feichu')){
							event.finish();
							return;
						}
						else{
							player.lose(event.card,'visible',ui.ordering);
							player.$phaseJudge(event.card);
							event.cancelled=false;
							event.trigger('phaseJudge');
							var name=event.card.viewAs||event.card.name;
							player.popup(name,'thunder');
							if(!lib.card[name].effect){
								game.delay();
								event.redo();
							}
							else if(!lib.card[name].judge){
								game.delay();
								event.nojudge=true;
							}
						}
					}
					else event.finish();
					"step 2"
					if(!event.cancelled&&!event.nojudge) player.judge(event.card).set('type','phase');
					"step 3"
					var name=event.card.viewAs||event.card.name;
					if(event.excluded){
						delete event.excluded;
					}
					else if(event.cancelled&&!event.direct){
						if(lib.card[name].cancel){
							var next=game.createEvent(name+'Cancel');
							next.setContent(lib.card[name].cancel);
							next.cards=[event.card];
							if(!event.card.viewAs) next.card=get.autoViewAs(event.card);
							else next.card=get.autoViewAs({name:name},next.cards);
							next.player=player;
						}
					}
					else{
						var next=game.createEvent(name);
						next.setContent(lib.card[name].effect);
						next._result=result;
						next.cards=[event.card];
						if(!event.card.viewAs) next.card=get.autoViewAs(event.card);
						else next.card=get.autoViewAs({name:name},next.cards);
						next.player=player;
					}
					ui.clear();
					event.goto(1);
				},
				phaseDraw:function(){
					"step 0"
					game.log(player,'进入了摸牌阶段');
					event.trigger("phaseDrawBegin1");
					"step 1"
					event.trigger("phaseDrawBegin2");
					"step 2"
					if(game.modPhaseDraw){
						game.modPhaseDraw(player,event.num);
					}
					else{
						if(event.num>0){
							var num=event.num;
							if(event.attachDraw){
								for(var i=0;i<event.attachDraw.length;i++){
									ui.cardPile.insertBefore(event.attachDraw[i],ui.cardPile.firstChild);
								}
								num+=event.attachDraw.length;
							}
							var next=player.draw(num);
							if(event.attachDraw){
								next.minnum=event.attachDraw.length;
							}
						}
					}
					"step 3"
					if(Array.isArray(result)){
						event.cards=result;
					}
				},
				phaseUse:function(){
					"step 0"
					if(!event.logged){
						game.log(player,'进入了出牌阶段');
						event.logged=true;
					}
					var next=player.chooseToUse();
					if(!lib.config.show_phaseuse_prompt){
						next.set('prompt',false);
					}
					next.set('type','phase');
					"step 1"
					if(result.bool&&!event.skipped){
						event.goto(0);
					}
					game.broadcastAll(function(){
						if(ui.tempnowuxie){
							ui.tempnowuxie.close();
							delete ui.tempnowuxie;
						}
					});
					"step 2"
					var stat=player.getStat();
					for(var i in stat.skill){
						var bool=false;
						var info=lib.skill[i];
						if(!info) continue;
						if(info.enable!=undefined){
							if(typeof info.enable=='string'&&info.enable=='phaseUse') bool=true;
							else if(typeof info.enable=='object'&&info.enable.contains('phaseUse')) bool=true;
						}
						if(bool) stat.skill[i]=0;
					}
					for(var i in stat.card){
						var bool=false;
						var info=lib.card[i];
						if(!info) continue;
						if(info.updateUsable=='phaseUse') stat.card[i]=0;
					}
				},
				phaseDiscard:function(){
					"step 0"
					game.log(player,'进入了弃牌阶段');
					event.num=player.needsToDiscard();
					if(event.num<=0) event.finish();
					else{
						game.broadcastAll(function(player){
							if(lib.config.show_phase_prompt){
								player.popup('弃牌阶段',null,false);
							}
						},player);
					}
					event.trigger('phaseDiscard');
					"step 1"
					player.chooseToDiscard(num,true)
					.set('useCache',true);
					"step 2"
					event.cards=result.cards;
				},
				phaseJieshu:function(){
					event.trigger(event.name);
					game.log(player,'进入了结束阶段');
				},
				chooseToUse:function(){
					"step 0"
					if(event.responded) return;
					if(game.modeSwapPlayer&&!_status.auto&&player.isUnderControl()&&!lib.filter.wuxieSwap(event)){
						game.modeSwapPlayer(player);
					}
					var skills=player.getSkills('invisible').concat(lib.skill.global);
					game.expandSkills(skills);
					for(var i=0;i<skills.length;i++){
						var info=lib.skill[skills[i]];
						if(info&&info.onChooseToUse){
							info.onChooseToUse(event);
						}
					}
					_status.noclearcountdown=true;
					if(event.type=='phase'){
						if(event.isMine()){
							event.endButton=ui.create.control('结束回合','stayleft',function(){
								var evt=_status.event;
								if(evt.name!='chooseToUse'||evt.type!='phase') return;
								if(evt.skill){
									ui.click.cancel();
								}
								ui.click.cancel();
							});
							event.fakeforce=true;
						}
						else{
							if(event.endButton){
								event.endButton.close();
								delete event.endButton;
							}
							event.fakeforce=false;
						}
					}
					if(event.player.isUnderControl()&&!_status.auto){
						event.result={
							bool:false
						}
						return;
					}
					else if(event.isMine()){
						if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
							ui.click.cancel();
							return;
						}
						if(event.type=='wuxie'){
							if(ui.tempnowuxie){
								var triggerevent=event.getTrigger();
								if(triggerevent&&triggerevent.targets&&triggerevent.num==triggerevent.targets.length-1){
									ui.tempnowuxie.close();
								}
							}
							if(lib.filter.wuxieSwap(event)){
								event.result={
									bool:false
								}
								return;
							}
						}
						var ok=game.check();
						if(!ok||!lib.config.auto_confirm){
							game.pause();
							if(lib.config.enable_vibrate&&player._noVibrate){
								delete player._noVibrate;
								game.vibrate();
							}
							if(typeof event.prompt=='string'){
								if(event.openskilldialog){
									event.skillDialog=ui.create.dialog(event.openskilldialog);
									delete event.openskilldialog;
									event.dialog=event.prompt;
								}
								else{
									event.dialog=ui.create.dialog(event.prompt);
									if(event.prompt2){
										event.dialog.addText(event.prompt2);
									}
								}
							}
							else if(typeof event.prompt=='function'){
								event.dialog=ui.create.dialog(event.prompt(event));
							}
							else if(event.prompt==undefined){
								var str;
								if(typeof event.filterCard=='object'){
									var filter=event.filterCard;
									str='请使用'+get.cnNumber(event.selectCard[0])+'张'
									if(filter.name){
										str+=get.translation(filter.name);
									}
									else{
										str+='牌';
									}
								}
								else{
									str='请选择要使用的牌';
								}
								if(event.openskilldialog){
									event.skillDialog=ui.create.dialog(event.openskilldialog);
									delete event.openskilldialog;
									event.dialog=str;
								}
								else if(typeof event.skillDialog!='string'){
									event.dialog=ui.create.dialog(str);
								}
								else{
									event.dialog=str;
								}
							}
						}
					}
					else if(event.isOnline()){
						event.send();
					}
					else{
						event.result='ai';
					}
					"step 1"
					if(event.result=='ai'){
						var ok=game.check();
						if(ok){
							ui.click.ok();
						}
						else if(ai.basic.chooseCard(event.ai1)||forced){
							if((ai.basic.chooseTarget(event.ai2)||forced)&&(!event.filterOk||event.filterOk())){
								ui.click.ok();
								event._aiexcludeclear=true;
							}
							else{
								if(!event.norestore){
									if(event.skill){
										var skill=event.skill;
										ui.click.cancel();
										event._aiexclude.add(skill);
										var info=get.info(skill);
										if(info.sourceSkill){
											event._aiexclude.add(info.sourceSkill);
										}
									}
									else{
										get.card(true).aiexclude();
										game.uncheck();
									}
									event.redo();
									game.resume();
								}
								else{
									ui.click.cancel();
								}
							}
						}
						else if(event.skill&&!event.norestore){
							var skill=event.skill;
							ui.click.cancel();
							event._aiexclude.add(skill);
							var info=get.info(skill);
							if(info.sourceSkill){
								event._aiexclude.add(info.sourceSkill);
							}
							event.redo();
							game.resume();
						}
						else{
							ui.click.cancel();
						}
						if(event.aidelay&&event.result&&event.result.bool){
							game.delayx();
						}
					}
					"step 2"
					if(event.endButton){
						event.endButton.close();
						delete event.endButton;
					}
					event.resume();
					if(event.result){
						if(event.result._sendskill){
							lib.skill[event.result._sendskill[0]]=event.result._sendskill[1];
						}
						if(event.result.skill){
							var info=get.info(event.result.skill);
							if(info&&info.chooseButton){
								if(event.dialog&&typeof event.dialog=='object') event.dialog.close();
								var dialog=info.chooseButton.dialog(event,player);
								if(info.chooseButton.chooseControl){
									var next=player.chooseControl(info.chooseButton.chooseControl(event,player));
									if(dialog.direct) next.direct=true;
									if(dialog.forceDirect) next.forceDirect=true;
									next.dialog=dialog;
									next.set('ai',info.chooseButton.check||function(){return 0;});
									if(event.id) next._parent_id=event.id;
									next.type='chooseToUse_button';
								}
								else{
									var next=player.chooseButton(dialog);
									if(dialog.direct) next.direct=true;
									if(dialog.forceDirect) next.forceDirect=true;
									next.set('ai',info.chooseButton.check||function(){return 1;});
									next.set('filterButton',info.chooseButton.filter||function(){return true;});
									next.set('selectButton',info.chooseButton.select||1);
									if(event.id) next._parent_id=event.id;
									next.type='chooseToUse_button';
								}
								event.buttoned=event.result.skill;
							}
							else if(info&&info.precontent&&!game.online&&!event.nouse){
								var next=game.createEvent('pre_'+event.result.skill);
								next.setContent(info.precontent);
								next.set('result',event.result);
								next.set('player',player);
							}
						}
					}
					"step 3"
					if(event.buttoned){
						if(result.bool||result.control&&result.control!='cancel2'){
							var info=get.info(event.buttoned).chooseButton;
							lib.skill[event.buttoned+'_backup']=info.backup(info.chooseControl?result:result.links,player);
							lib.skill[event.buttoned+'_backup'].sourceSkill=event.buttoned;
							if(game.online){
								event._sendskill=[event.buttoned+'_backup',lib.skill[event.buttoned+'_backup']];
							}
							event.backup(event.buttoned+'_backup');
							if(info.prompt){
								event.openskilldialog=info.prompt(info.chooseControl?result:result.links,player);
							}
						}
						else{
							ui.control.animate('nozoom',100);
							event._aiexclude.add(event.buttoned);
						}
						event.goto(0);
						delete event.buttoned;
					}
					"step 4"
					if(event._aiexcludeclear){
						delete event._aiexcludeclear;
						event._aiexclude.length=0;
					}
					delete _status.noclearcountdown;
					if(event.skillDialog&&get.objtype(event.skillDialog)=='div'){
						event.skillDialog.close();
					}
					if(event.result&&event.result.bool&&!game.online&&!event.nouse){
						player.useResult(event.result,event);
					}
					else if(event._sendskill){
						event.result._sendskill=event._sendskill;
					}
					if(event.dialog&&typeof event.dialog=='object') event.dialog.close();
					if(!_status.noclearcountdown){
						game.stopCountChoose();
					}
					"step 5"
					if(event._result&&event.result){
						event.result.result=event._result;
					}
				},
				chooseToRespond:function(){
					"step 0"
					if(event.responded){
						delete event.dialog;
						return;
					}
					var skills=player.getSkills('invisible').concat(lib.skill.global);
					game.expandSkills(skills);
					for(var i=0;i<skills.length;i++){
						var info=lib.skill[skills[i]];
						if(info&&info.onChooseToRespond){
							info.onChooseToRespond(event);
						}
					}
					_status.noclearcountdown=true;
					if(!_status.connectMode&&lib.config.skip_shan&&event.autochoose&&event.autochoose()){
						event.result={bool:false};
					}
					else{
						if(game.modeSwapPlayer&&!_status.auto&&player.isUnderControl()){
							game.modeSwapPlayer(player);
						}
						if(event.isMine()){
							if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
								ui.click.cancel();
								return;
							}
							var ok=game.check();
							if(!ok||!lib.config.auto_confirm){
								game.pause();
								if(event.openskilldialog){
									event.skillDialog=ui.create.dialog(event.openskilldialog);
									delete event.openskilldialog;
									event.dialog=event.prompt;
								}
								else{
									if(event.prompt) event.dialog=ui.create.dialog(event.prompt);
									if(event.prompt2) event.dialog.addText(event.prompt2);
								}
							}
						}
						else if(event.isOnline()){
							event.send();
						}
						else{
							event.result='ai';
						}
					}
					"step 1"
					if(event.result=='ai'){
						var ok=game.check();
						if(ok){
							ui.click.ok();
						}
						else if(ai.basic.chooseCard(event.ai1||event.ai)||forced){
							if((ai.basic.chooseTarget(event.ai2)||forced)&&(!event.filterOk||event.filterOk())){
								ui.click.ok();
								event._aiexcludeclear=true;
							}
							else{
								if(!event.norestore){
									if(event.skill){
										var skill=event.skill;
										ui.click.cancel();
										event._aiexclude.add(skill);
										var info=get.info(skill);
										if(info.sourceSkill){
											event._aiexclude.add(info.sourceSkill);
										}
									}
									else{
										get.card(true).aiexclude();
										game.uncheck();
									}
									event.redo();
									game.resume();
								}
								else{
									ui.click.cancel();
								}
							}
						}
						else if(event.skill&&!event.norestore){
							var skill=event.skill;
							ui.click.cancel();
							event._aiexclude.add(skill);
							var info=get.info(skill);
							if(info.sourceSkill){
								event._aiexclude.add(info.sourceSkill);
							}
							event.redo();
							game.resume();
						}
						else{
							ui.click.cancel();
						}
						if(event.aidelay&&event.result&&event.result.bool){
							game.delayx();
						}
					}
					"step 2"
					event.resume();
					if(event.result){
						if(event.result._sendskill){
							lib.skill[event.result._sendskill[0]]=event.result._sendskill[1];
						}
						if(event.result.skill){
							var info=get.info(event.result.skill);
							if(info&&info.chooseButton){
								if(event.dialog&&typeof event.dialog=='object') event.dialog.close();
								var dialog=info.chooseButton.dialog(event,player);
								if(info.chooseButton.chooseControl){
									var next=player.chooseControl(info.chooseButton.chooseControl(event,player));
									if(dialog.direct) next.direct=true;
									if(dialog.forceDirect) next.forceDirect=true;
									next.dialog=dialog;
									next.set('ai',info.chooseButton.check||function(){return 0;});
								}
								else{
									var next=player.chooseButton(dialog);
									if(dialog.direct) next.direct=true;
									if(dialog.forceDirect) next.forceDirect=true;
									next.set('ai',info.chooseButton.check||function(){return 1;});
									next.set('filterButton',info.chooseButton.filter||function(){return true;});
									next.set('selectButton',info.chooseButton.select||1);
								}
								event.buttoned=event.result.skill;
							}
							else if(info&&info.precontent&&!game.online){
								var next=game.createEvent('pre_'+event.result.skill);
								next.setContent(info.precontent);
								next.set('result',event.result);
								next.set('player',player);
							}
						}
					}
					"step 3"
					if(event.buttoned){
						if(result.bool||result.control&&result.control!='cancel2'){
							var info=get.info(event.buttoned).chooseButton;
							lib.skill[event.buttoned+'_backup']=info.backup(info.chooseControl?result:result.links,player);
							lib.skill[event.buttoned+'_backup'].sourceSkill=event.buttoned;
							if(game.online){
								event._sendskill=[event.buttoned+'_backup',lib.skill[event.buttoned+'_backup']];
							}
							event.backup(event.buttoned+'_backup');
							if(info.prompt){
								event.openskilldialog=info.prompt(info.chooseControl?result:result.links,player);
							}
						}
						else{
							ui.control.animate('nozoom',100);
							event._aiexclude.add(event.buttoned);
						}
						event.goto(0);
						delete event.buttoned;
					}
					"step 4"
					delete _status.noclearcountdown;
					if(event.skillDialog&&get.objtype(event.skillDialog)=='div'){
						event.skillDialog.close();
					}
					if(event.result.bool&&!game.online){
						if(event.result._sendskill){
							lib.skill[event.result._sendskill[0]]=event.result._sendskill[1];
						}
						var info=get.info(event.result.skill);
						if(event.onresult){
							event.onresult(event.result);
						}
						if(event.result.skill){
							if(info.direct&&!info.clearTime){
								_status.noclearcountdown=true;
							}
						}
						if(event.logSkill){
							if(typeof event.logSkill=='string'){
								player.logSkill(event.logSkill);
							}
							else if(Array.isArray(event.logSkill)){
								player.logSkill.apply(player,event.logSkill);
							}
						}
						if(!event.result.card&&event.result.skill){
							event.result.used=event.result.skill;
							player.useSkill(event.result.skill,event.result.cards,event.result.targets);
						}
						else{
							if(info&&info.prerespond){
								info.prerespond(event.result,player);
							}
							var next=player.respond(event.result.cards,event.result.card,event.animate,event.result.skill,event.source);
							if(event.result.noanimate) next.animate=false;
							if(event.parent.card&&event.parent.type=='card'){
								next.set('respondTo',[event.parent.player,event.parent.card]);
							}
							if(event.noOrdering) next.noOrdering=true;
						}
					}
					else if(event._sendskill){
						event.result._sendskill=event._sendskill;
					}
					if(event.dialog&&event.dialog.close) event.dialog.close();
					if(!_status.noclearcountdown){
						game.stopCountChoose();
					}
				},
				chooseToDiscard:function(){
					"step 0"
					if(event.autochoose()){
						event.result={
							bool:true,
							autochoose:true,
							cards:player.getCards(event.position),
							rawcards:player.getCards(event.position),
						}
						for(var i=0;i<event.result.cards.length;i++){
							if(!lib.filter.cardDiscardable(event.result.cards[i],player,event)){
								event.result.cards.splice(i--,1);
							}
						}
					}
					else{
						// &&!lib.filter.wuxieSwap(trigger)
						if(game.modeSwapPlayer&&!_status.auto&&player.isUnderControl()){
							game.modeSwapPlayer(player);
						}
						event.rangecards=player.getCards(event.position);
						for(var i=0;i<event.rangecards.length;i++){
							if(lib.filter.cardDiscardable(event.rangecards[i],player,event)){
								event.rangecards.splice(i--,1);
							}
							else{
								event.rangecards[i].uncheck('chooseToDiscard');
							}
						}
						var range=get.select(event.selectCard);
						if(event.isMine()){
							game.check();
							if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
								ui.click.cancel();
								return;
							}
							game.pause();
							if(range[1]>1&&typeof event.selectCard!='function'){
								event.promptdiscard=ui.create.control('AI代选',function(){
									ai.basic.chooseCard(event.ai);
									if(_status.event.custom&&_status.event.custom.add.card){
										_status.event.custom.add.card();
									}
									for(var i=0;i<ui.selected.cards.length;i++){
										ui.selected.cards[i].updateTransform(true);
									}
								});
							}
							if(Array.isArray(event.dialog)){
								event.dialog=ui.create.dialog.apply(this,event.dialog);
								event.dialog.open();
								event.dialog.classList.add('noselect');
							}
							else if(event.prompt!=false){
								var str;
								if(typeof(event.prompt)=='string') str=event.prompt;
								else{
									str='请弃置';
									if(range[0]==range[1]) str+=get.cnNumber(range[0]);
									else if(range[1]==Infinity) str+='至少'+get.cnNumber(range[0]);
									else str+=get.cnNumber(range[0])+'至'+get.cnNumber(range[1]);
									str+='张';
									if(event.position=='h'||event.position==undefined) str+='手';
									if(event.position=='e') str+='装备';
									str+='牌';
								}
								event.dialog=ui.create.dialog(str);
								if(event.prompt2){
									event.dialog.addText(event.prompt2,event.prompt2.length<=20);
								}
								if(Array.isArray(event.selectCard)){
									event.promptbar=event.dialog.add('0/'+get.numStr(event.selectCard[1],'card'));
									event.custom.add.card=function(){
										_status.event.promptbar.innerHTML=
										ui.selected.cards.length+'/'+get.numStr(_status.event.selectCard[1],'card');
									}
								}
							}
							else if(get.itemtype(event.dialog)=='dialog'){
								event.dialog.style.display='';
								event.dialog.open();
							}
						}
						else if(event.isOnline()){
							event.send();
						}
						else{
							event.result='ai';
						}
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if((ai.basic.chooseCard(event.ai)||forced)&&(!event.filterOk||event.filterOk())){
							ui.click.ok();
						}
						else if(event.skill){
							var skill=event.skill;
							ui.click.cancel();
							event._aiexclude.add(skill);
							event.redo();
							game.resume();
						}
						else{
							ui.click.cancel();
						}
					}
					if(event.rangecards){
						for(var i=0;i<event.rangecards.length;i++){
							event.rangecards[i].recheck('chooseToDiscard');
						}
					}
					"step 2"
					event.resume();
					if(event.promptdiscard){
						event.promptdiscard.close();
					}
					"step 3"
					if(event.result.bool&&event.result.cards&&event.result.cards.length&&
						!game.online&&event.autodelay&&!event.isMine()){
						if(typeof event.autodelay=='number'){
							game.delayx(event.autodelay);
						}
						else{
							game.delayx();
						}
					}
					"step 4"
					if(event.logSkill&&event.result.bool&&!game.online){
						if(typeof event.logSkill=='string'){
							player.logSkill(event.logSkill);
						}
						else if(Array.isArray(event.logSkill)){
							player.logSkill.apply(player,event.logSkill);
						}
					}
					if(!game.online){
						if(typeof event.delay=='boolean'){
							event.done=player.discard(event.result.cards).set('delay',event.delay);
						}
						else{
							event.done=player.discard(event.result.cards);
						}
						event.done.discarder=player;
					}
					if(event.dialog&&event.dialog.close) event.dialog.close();
				},
				gaincardMultiple:function(){
					'step 0'
					event.type='gain';
					if(event.animate=='give'||event.animate=='gain2') event.visible=true;
					if(player&&cards){
						event._lose=true;
						player.lose(cards,ui.special).set('type','gain').set('forceDie',true).set('getlx',false);
					}
					'step 1'
					switch(event.animate){
						case 'draw':
							game.delay(0,get.delayx(500,500));
							for(var i of event.gain_list){
								if(get.itemtype(i[1])=='card') i[1]=[i[1]];
								if(event._lose){
									i[1]=i[1].filter(card=>{
										return !cards.contains(card)||!player.getCards('hejsx').contains(card);
									})
								}
								if(i[1].length>0) i[0].$draw(i[1].length);
							}
							break;
						case 'gain':
							game.delay(0,get.delayx(700,700));
							for(var i of event.gain_list){
								if(get.itemtype(i[1])=='card') i[1]=[i[1]];
								if(event._lose){
									i[1]=i[1].filter(card=>{
										return !cards.contains(card)||!player.getCards('hejsx').contains(card);
									})
								}
								if(i[1].length>0) i[0].$gain(i[1].length);
							}
							break;
						case 'gain2': case 'draw2':
							game.delay(0,get.delayx(500,500));
							for(var i of event.gain_list){
								if(get.itemtype(i[1])=='card') i[1]=[i[1]];
								if(event._lose){
									i[1]=i[1].filter(card=>{
										return !cards.contains(card)||!player.getCards('hejsx').contains(card);
									})
								}
								if(i[1].length>0) i[0].$gain2(i[1]);
							}
							break;
						case 'give': case 'giveAuto':
							if(!player) break;
							var evt=event.getl(player);
							game.delay(0,get.delayx(500,500));
							for(var i of event.gain_list){
								if(get.itemtype(i[1])=='card') i[1]=[i[1]];
								if(event._lose){
									i[1]=i[1].filter(card=>{
										return !cards.contains(card)||!player.getCards('hejsx').contains(card);
									})
								}
								var shown=i[1].slice(0),hidden=[];
								if(event.animate=='giveAuto'){
									for(var card of i[1]){
										if(evt.hs.contains(card)){
											shown.remove(card);
											hidden.push(card);
										}
									}
								}
								if(shown.length>0) player.$give(shown,i[0]);
								if(hidden.length>0) player.$giveAuto(hidden,i[0]);
							}
							break;
						default:
							event.finish();
					}
					for(var i of event.gain_list){
						if(i[1].length>0){
							var next=i[0].gain(i[1]);
							next.getlx=false;
							if(event.visible) next.visible=true;
							if(event.giver) next.giver=event.giver;
							if(event.gaintag) next.gaintag.addArray(event.gaintag);
						}
					}
					'step 2'
					game.delayx();
				},
				discardMultiple:function(){
					'step 0'
					event.type='discard';
					event.visible=true;
					if(!event.position) event.position=ui.discardPile;
					var cards=[];
					event.cards=cards;
					for(var i=0;i<event.lose_list.length;i++){
						var next=event.lose_list[i][0].lose(event.lose_list[i][1],event.position);
						game.log(event.lose_list[i][0],'弃置了',event.lose_list[i][1]);
						next.type='discard';
						next.animate=false;
						next.delay=false;
						cards.addArray(event.lose_list[i][1]);
						next.getlx=false;
					}
					var evt=event;
					if(evt.animate!=false){
						evt.discardid=lib.status.videoId++;
						game.broadcastAll(function(list,id,cards){
							for(var i of list){
								for(var j of i[1]){
									j.classList.remove('glow');
									j.classList.remove('glows');
								}
								i[0].$throw(i[1],null,'nobroadcast');
							}
							var cardnodes=[];
							cardnodes._discardtime=get.time();
							for(var ix of list){
								var card=ix[1];
								for(var i=0;i<cards.length;i++){
									if(cards[i].clone){
										cardnodes.push(cards[i].clone);
									}
								}
							}
							ui.todiscard[id]=cardnodes;
						},event.lose_list,evt.discardid,cards);
						if(lib.config.sync_speed&&cards[0]&&cards[0].clone){
							if(evt.delay!=false){
								var waitingForTransition=get.time();
								evt.waitingForTransition=waitingForTransition;
								cards[0].clone.listenTransition(function(){
									if(_status.waitingForTransition==waitingForTransition&&_status.paused){
										game.resume();
									}
									delete evt.waitingForTransition;
								});
							}
							else if(evt.getParent().discardTransition){
								delete evt.getParent().discardTransition;
								var waitingForTransition=get.time();
								evt.getParent().waitingForTransition=waitingForTransition;
								cards[0].clone.listenTransition(function(){
									if(_status.waitingForTransition==waitingForTransition&&_status.paused){
										game.resume();
									}
									delete evt.getParent().waitingForTransition;
								});
							}
						}
					}
					'step 1'
					if(event.delay!=false){
						if(event.waitingForTransition){
							_status.waitingForTransition=event.waitingForTransition;
							game.pause();
						}
						else{
							game.delayx();
						}
					}
				},
				chooseToCompareLose:function(){
					for(var i=0;i<event.lose_list.length;i++){
						var next=event.lose_list[i][0].lose(event.lose_list[i][1],ui.ordering);
						next.relatedEvent=event.getParent();
						next.getlx=false;
					}
				},
				chooseToCompareMeanwhile:function(){
					'step 0'
					if(player.countCards('h')==0){
						event.result={cancelled:true,bool:false}
						event.finish();
						return;
					}
					for(var i=0; i<targets.length; i++){
						if(targets[i].countCards('h')==0){
							event.result={cancelled:true,bool:false}
							event.finish();
							return;
						}
					}
					if(!event.multitarget){
						targets.sort(lib.sort.seat);
					}
					game.log(player,'对',targets,'发起了共同拼点');
					event.compareMeanwhile=true;
					'step 1'
					event._result=[];
					event.list=targets.filter(function(current){
						return !event.fixedResult||!event.fixedResult[current.playerid];
					});
					if(event.list.length||!event.fixedResult||!event.fixedResult[player.playerid]){
						if(!event.fixedResult||!event.fixedResult[player.playerid]) event.list.unshift(player);
						player.chooseCardOL(event.list,'请选择拼点牌',true).set('type','compare').set('ai',event.ai).set('source',player).aiCard=function(target){
							var hs=target.getCards('h');
							var event=_status.event;
							event.player=target;
							hs.sort(function(a,b){
								return event.ai(b)-event.ai(a);
							});
							delete event.player;
							return {bool:true,cards:[hs[0]]};
						};
					}
					'step 2'
					var cards=[];
					var lose_list=[];
					if(event.fixedResult&&event.fixedResult[player.playerid]){
						event.list.unshift(player);
						result.unshift({bool:true,cards:[event.fixedResult[player.playerid]]});
						lose_list.push([player,[event.fixedResult[player.playerid]]]);
					}
					else{
						if(result[0].skill&&lib.skill[result[0].skill]&&lib.skill[result[0].skill].onCompare){
							player.logSkill(result[0].skill);
							result[0].cards=lib.skill[result[0].skill].onCompare(player)
						}
						else lose_list.push([player,result[0].cards]);
					};
					for(var j=0; j<targets.length; j++){
						if(event.list.contains(targets[j])){
							var i=event.list.indexOf(targets[j]);
							if(result[i].skill&&lib.skill[result[i].skill]&&lib.skill[result[i].skill].onCompare){
								event.list[i].logSkill(result[i].skill);
								result[i].cards=lib.skill[result[i].skill].onCompare(event.list[i]);
							}
							else lose_list.push([targets[j],result[i].cards]);
							cards.push(result[i].cards[0]);
						}
						else if(event.fixedResult&&event.fixedResult[targets[j].playerid]){
							cards.push(event.fixedResult[targets[j].playerid]);
							lose_list.push([targets[j],[event.fixedResult[targets[j].playerid]]]);
						}
					}
					if(lose_list.length){
						game.loseAsync({
							lose_list:lose_list,
						}).setContent('chooseToCompareLose');
					}
					event.lose_list=lose_list;
					event.getNum=function(card){
						for(var i of event.lose_list){
							if(i[1].contains&&i[1].contains(card)) return get.number(card,i[0]);
						}
						return get.number(card,false);
					}
					event.cardlist=cards;
					event.cards=cards;
					event.card1=result[0].cards[0];
					event.num1=event.getNum(event.card1);
					event.iwhile=0;
					event.winner=null;
					event.maxNum=-1;
					event.tempplayer=event.player;
					event.result={
						winner:null,
						player:event.card1,
						targets:event.cardlist.slice(0),
						num1:[],
						num2:[],
					};
					'step 3'
					event.trigger('compareCardShowBefore');
					'step 4'
					player.$compareMultiple(event.card1,targets,cards);
					game.log(player,'的拼点牌为',event.card1);
					player.animate('target');
					game.delay(0,1000);
					'step 5'
					event.target=null;
					event.trigger('compare');
					'step 6'
					if(event.iwhile<targets.length){
						event.target=targets[event.iwhile];
						event.target.animate('target');
						event.card2=event.cardlist[event.iwhile];
						event.num2=event.getNum(event.card2);
						game.log(event.target,'的拼点牌为',event.card2);
						//event.tempplayer.line(event.target);
						delete event.player;
						event.trigger('compare');
					}
					else{
						game.delay(0,1000);
						event.goto(9);
					}
					'step 7'
					event.result.num1[event.iwhile]=event.num1;
					event.result.num2[event.iwhile]=event.num2;
					var list=[[event.tempplayer,event.num1],[event.target,event.num2]];
					for(var i of list){
						if(i[1]>event.maxNum){
							event.maxNum=i[1];
							event.winner=i[0];
						}
						else if(event.winner&&i[1]==event.maxNum&&i[0]!=event.winner){
							event.winner=null;
						}
					}
					'step 8'
					event.iwhile++;
					event.goto(6);
					'step 9'
					var player=event.tempplayer;
					event.player=player;
					delete event.tempplayer;
					var str='无人拼点成功';
					if(event.winner){
						event.result.winner=event.winner;
						str=get.translation(event.winner)+'拼点成功';
						game.log(event.winner,'拼点成功');
						event.winner.popup('胜');
					} else game.log('#b无人','拼点成功');
					var list=[player].addArray(targets);
					list.remove(event.winner);
					for(var i of list){
						i.popup('负');
					}
					if(str){
						game.broadcastAll(function(str){
							var dialog=ui.create.dialog(str);
							dialog.classList.add('center');
							setTimeout(function(){
								dialog.close();
							},1000);
						},str);
					}
					game.delay(3);
					'step 10'
					game.broadcastAll(ui.clear);
					'step 11'
					event.cards.add(event.card1);
				},
				chooseToCompareMultiple:function(){
					"step 0"
					if(player.countCards('h')==0){
						event.result={cancelled:true,bool:false}
						event.finish();
						return;
					}
					for(var i=0;i<targets.length;i++){
						if(targets[i].countCards('h')==0){
							event.result={cancelled:true,bool:false}
							event.finish();
							return;
						}
					}
					if(!event.multitarget){
						targets.sort(lib.sort.seat);
					}
					game.log(player,'对',targets,'发起拼点');
					"step 1"
					event._result=[];
					event.list=targets.filter(function(current){
						return !event.fixedResult||!event.fixedResult[current.playerid];
					});
					if(event.list.length||!event.fixedResult||!event.fixedResult[player.playerid]){
						if(!event.fixedResult||!event.fixedResult[player.playerid]) event.list.unshift(player);
						player.chooseCardOL(event.list,'请选择拼点牌',true).set('type','compare').set('ai',event.ai).set('source',player).aiCard=function(target){
							var hs=target.getCards('h');
							var event=_status.event;
							event.player=target;
							hs.sort(function(a,b){
								return event.ai(b)-event.ai(a);
							});
							delete event.player;
							return {bool:true,cards:[hs[0]]};
						};
					}
					"step 2"
					var cards=[];
					var lose_list=[];
					if(event.fixedResult&&event.fixedResult[player.playerid]){
						event.list.unshift(player);
						result.unshift({bool:true,cards:[event.fixedResult[player.playerid]]});
						lose_list.push([player,[event.fixedResult[player.playerid]]]);
					}
					else{
						if(result[0].skill&&lib.skill[result[0].skill]&&lib.skill[result[0].skill].onCompare){
							player.logSkill(result[0].skill);
							result[0].cards=lib.skill[result[0].skill].onCompare(player)
						}
						else lose_list.push([player,result[0].cards]);
					};
					for(var j=0;j<targets.length;j++){
						if(event.list.contains(targets[j])){
							var i=event.list.indexOf(targets[j]);
							if(result[i].skill&&lib.skill[result[i].skill]&&lib.skill[result[i].skill].onCompare){
								event.list[i].logSkill(result[i].skill);
								result[i].cards=lib.skill[result[i].skill].onCompare(event.list[i]);
							}
							else lose_list.push([targets[j],result[i].cards]);
							cards.push(result[i].cards[0]);
						}
						else if(event.fixedResult&&event.fixedResult[targets[j].playerid]){
							cards.push(event.fixedResult[targets[j].playerid]);
							lose_list.push([targets[j],[event.fixedResult[targets[j].playerid]]]);
						}
					}
					if(lose_list.length){
						game.loseAsync({
							lose_list:lose_list,
						}).setContent('chooseToCompareLose');
					}
					event.lose_list=lose_list;
					event.getNum=function(card){
						for(var i of event.lose_list){
							if(i[1].contains&&i[1].contains(card)) return get.number(card,i[0]);
						}
						return get.number(card,false);
					}
					event.cardlist=cards;
					event.cards=cards;
					event.card1=result[0].cards[0];
					event.num1=event.getNum(event.card1);
					event.iwhile=0;
					event.result={
						player:event.card1,
						targets:event.cardlist.slice(0),
						num1:[],
						num2:[],
					};
					"step 3"
					event.trigger('compareCardShowBefore');
					"step 4"
					game.log(player,'的拼点牌为',event.card1);
					"step 5"
					if(event.iwhile<targets.length){
						event.target=targets[event.iwhile];
						event.target.animate('target');
						player.animate('target');
						event.card2=event.cardlist[event.iwhile];
						event.num2=event.getNum(event.card2);
						game.log(event.target,'的拼点牌为',event.card2);
						player.line(event.target);
						player.$compare(event.card1,event.target,event.card2);
						event.trigger('compare');
						game.delay(0,1500);
					}
					else{
						event.goto(9);
					}
					"step 6"
					event.result.num1[event.iwhile]=event.num1;
					event.result.num2[event.iwhile]=event.num2;
					var str;
					if(event.num1>event.num2){
						str=get.translation(player)+'拼点成功';
						player.popup('胜');
						target.popup('负');
					}
					else{
						str=get.translation(player)+'拼点失败';
						if(event.num1==event.num2){
							player.popup('平');
							target.popup('平');
						}
						else{
							player.popup('负');
							target.popup('胜');
						}
					}
					game.broadcastAll(function(str){
						var dialog=ui.create.dialog(str);
						dialog.classList.add('center');
						setTimeout(function(){
							dialog.close();
						},1000);
					},str);
					game.delay(2);
					"step 7"
					if(event.callback){
						game.broadcastAll(function(card1,card2){
							if(card1.clone) card1.clone.style.opacity=0.5;
							if(card2.clone) card2.clone.style.opacity=0.5;
						},event.card1,event.card2);
						var next=game.createEvent('compareMultiple');
						next.player=player;
						next.target=event.target;
						next.card1=event.card1;
						next.card2=event.card2;
						next.num1=event.num1;
						next.num2=event.num2;
						next.setContent(event.callback);
						event.compareMultiple=true;
					}
					"step 8"
					game.broadcastAll(ui.clear);
					event.iwhile++;
					event.goto(5);
					"step 9"
					event.cards.add(event.card1);
				},
				chooseToCompare:function(){
					"step 0"
					if(((!event.fixedResult||!event.fixedResult[player.playerid])&&player.countCards('h')==0)||((!event.fixedResult||!event.fixedResult[target.playerid])&&target.countCards('h')==0)){
						event.result={cancelled:true,bool:false}
						event.finish();
						return;
					}
					game.log(player,'对',target,'发起拼点');
					event.lose_list=[];
					"step 1"
					var sendback=function(){
						if(_status.event!=event){
							return function(){
								event.resultOL=_status.event.resultOL;
							};
						}
					};
					if(event.fixedResult&&event.fixedResult[player.playerid]){
						event.card1=event.fixedResult[player.playerid];
						event.lose_list.push([player,event.card1]);
					}
					else if(player.isOnline()){
						player.wait(sendback);
						event.ol=true;
						player.send(function(ai){
							game.me.chooseCard('请选择拼点牌',true).set('type','compare').set('glow_result',true).ai=ai;
							game.resume();
						},event.ai);
					}
					else{
						event.localPlayer=true;
						player.chooseCard('请选择拼点牌',true).set('type','compare').set('glow_result',true).ai=event.ai;
					}
					if(event.fixedResult&&event.fixedResult[target.playerid]){
						event.card2=event.fixedResult[target.playerid];
						event.lose_list.push([target,event.card2]);
					}
					else if(target.isOnline()){
						target.wait(sendback);
						event.ol=true;
						target.send(function(ai){
							game.me.chooseCard('请选择拼点牌',true).set('type','compare').set('glow_result',true).ai=ai;
							game.resume();
						},event.ai);
					}
					else{
						event.localTarget=true;
					}
					"step 2"
					if(event.localPlayer){
						if(result.skill&&lib.skill[result.skill]&&lib.skill[result.skill].onCompare){
							result.cards=lib.skill[result.skill].onCompare(player);
							player.logSkill(result.skill);
						}
						else event.lose_list.push([player,result.cards[0]]);
						event.card1=result.cards[0];
					}
					if(event.localTarget){
						target.chooseCard('请选择拼点牌',true).set('type','compare').set('glow_result',true).ai=event.ai;
					}
					"step 3"
					if(event.localTarget){
						if(result.skill&&lib.skill[result.skill]&&lib.skill[result.skill].onCompare){
							target.logSkill(result.skill);
							result.cards=lib.skill[result.skill].onCompare(target);
						}
						else event.lose_list.push([target,result.cards[0]]);
						event.card2=result.cards[0];
					}
					if(!event.resultOL&&event.ol){
						game.pause();
					}
					"step 4"
					try{
						if(!event.card1){
							if(event.resultOL[player.playerid].skill&&lib.skill[event.resultOL[player.playerid].skill]&&lib.skill[event.resultOL[player.playerid].skill].onCompare){
								player.logSkill(event.resultOL[player.playerid].skill);
								event.resultOL[player.playerid].cards=lib.skill[event.resultOL[player.playerid].skill].onCompare(player);
							}
							else event.lose_list.push([player,event.resultOL[player.playerid].cards[0]]);
							event.card1=event.resultOL[player.playerid].cards[0];
						};
						if(!event.card2){
							if(event.resultOL[target.playerid].skill&&lib.skill[event.resultOL[target.playerid].skill]&&lib.skill[event.resultOL[target.playerid].skill].onCompare){
								target.logSkill(event.resultOL[target.playerid].skill);
								event.resultOL[target.playerid].cards=lib.skill[event.resultOL[target.playerid].skill].onCompare(player);
							}
							else event.lose_list.push([target,event.resultOL[target.playerid].cards[0]]);
							event.card2=event.resultOL[target.playerid].cards[0];
						}
						if(!event.card1||!event.card2){
							throw('err');
						}
					}
					catch(e){
						console.log(e);
						game.print(e);
						event.finish();
						return;
					}
					if(event.card2.number>=10||event.card2.number<=4){
						if(target.countCards('h')>2){
							event.addToAI=true;
						}
					}
					if(event.lose_list.length){
						game.loseAsync({
							lose_list:event.lose_list,
						}).setContent('chooseToCompareLose');
					}
					"step 5"
					event.trigger('compareCardShowBefore');
					"step 6"
					game.broadcast(function(){
						ui.arena.classList.add('thrownhighlight');
					});
					ui.arena.classList.add('thrownhighlight');
					game.addVideo('thrownhighlight1');
					player.$compare(event.card1,target,event.card2);
					game.log(player,'的拼点牌为',event.card1);
					game.log(target,'的拼点牌为',event.card2);
					var getNum=function(card){
						for(var i of event.lose_list){
							if(i[1]==card) return get.number(card,i[0]);
						}
						return get.number(card,false);
					}
					event.num1=getNum(event.card1);
					event.num2=getNum(event.card2);
					event.trigger('compare');
					game.delay(0,1500);
					"step 7"
					event.result={
						player:event.card1,
						target:event.card2,
						num1:event.num1,
						num2:event.num2
					}
					var str;
					if(event.num1>event.num2){
						event.result.bool=true;
						event.result.winner=player;
						str=get.translation(player)+'拼点成功';
						player.popup('胜');
						target.popup('负');
					}
					else{
						event.result.bool=false;
						str=get.translation(player)+'拼点失败';
						if(event.num1==event.num2){
							event.result.tie=true;
							player.popup('平');
							target.popup('平');
						}
						else{
							event.result.winner=target;
							player.popup('负');
							target.popup('胜');
						}
					}
					game.broadcastAll(function(str){
						var dialog=ui.create.dialog(str);
						dialog.classList.add('center');
						setTimeout(function(){
							dialog.close();
						},1000);
					},str);
					game.delay(2);
					"step 8"
					if(typeof event.target.ai.shown=='number'&&event.target.ai.shown<=0.85&&event.addToAI){
						event.target.ai.shown+=0.1;
					}
					game.broadcastAll(function(){
						ui.arena.classList.remove('thrownhighlight');
					});
					game.addVideo('thrownhighlight2');
					if(event.clear!==false){
						game.broadcastAll(ui.clear);
					}
					if(typeof event.preserve=='function'){
						event.preserve=event.preserve(event.result);
					}
					else if(event.preserve=='win'){
						event.preserve=event.result.bool;
					}
					else if(event.preserve=='lose'){
						event.preserve=!event.result.bool;
					}
				},
				chooseSkill:function(){
					'step 0'
					var list;
					if(typeof event.target=='string'){
						list=get.gainableSkillsName(event.target,event.func);
					}
					else{
						list=event.target.getGainableSkills(event.func);
					}
					if(!list.length){
						event.finish();
						event.result={bool:false};
						return;
					}
					event.skillai=function(list){
						return get.max(list,get.skillRank,'item');
					};
					if(event.isMine()){
						var dialog=ui.create.dialog('forcebutton');
						dialog.add(event.prompt||'选择获得一项技能');
						_status.event.list=list;
						var clickItem=function(){
							_status.event._result=this.link;
							game.resume();
						};
						for(i=0;i<list.length;i++){
							if(lib.translate[list[i]+'_info']){
								var translation=get.translation(list[i]);
								if(translation[0]=='新'&&translation.length==3){
									translation=translation.slice(1,3);
								}
								else{
									translation=translation.slice(0,2);
								}
								var item=dialog.add('<div class="popup pointerdiv" style="width:80%;display:inline-block"><div class="skill">【'+
								translation+'】</div><div>'+lib.translate[list[i]+'_info']+'</div></div>');
								item.firstChild.addEventListener('click',clickItem);
								item.firstChild.link=list[i];
							}
						}
						dialog.add(ui.create.div('.placeholder'));
						event.dialog=dialog;
						event.switchToAuto=function(){
							event._result=event.skillai(event.list);
							game.resume();
						};
						_status.imchoosing=true;
						game.pause();
					}
					else{
						event._result=event.skillai(list);
					}
					'step 1'
					_status.imchoosing=false;
					if(event.dialog){
						event.dialog.close();
					}
					event.result={bool:true,skill:result};
				},
				discoverCard:function(){
					'step 0'
					var num=event.num||3;
					var choice;
					if(typeof event.list=='string'||typeof event.list=='function'){
						choice=get.inpile(event.list).randomGets(num);
					}
					else if(Array.isArray(event.list)){
						choice=event.list.randomGets(num);
					}
					else{
						choice=Array.from(event.list).randomGets(num);
					}
					if(choice.length){
						var prompt=event.prompt;
						if(!prompt){
							prompt='选择一张牌';
							if(event.use){
								prompt+='使用之';
							}
							else if(!event.nogain){
								prompt+='获得之';
							}
						}
						if(typeof choice[0]==='string'){
							var next=player.chooseVCardButton(choice,prompt,event.forced);
							if(event.ai){
								next.set('ai',event.ai);
							}
						}
						else if(get.itemtype(choice[0])=='card'){
							var next=player.chooseCardButton(choice,prompt,event.forced);
							if(event.ai){
								next.set('ai',event.ai);
							}
						}
						else{
							event.finish();
						}
					}
					else{
						event.finish();
					}
					'step 1'
					event.result={
						bool:result.bool,
						card:null,
						choice:null
					};
					if(result.bool&&result.links.length){
						var link=result.links[0];
						var togain=null;
						if(get.itemtype(link)=='card'){
							event.result.card=link;
							togain=link;
						}
						else if(Array.isArray(link)){
							event.result.choice=link[2];
							togain=game.createCard(link[2]);
						}
						if(togain){
							if(event.use){
								player.chooseUseTarget(togain);
							}
							else if(!event.nogain){
								player.gain(togain,'draw');
								game.log(player,'获得了一张牌');
							}
						}
					}
				},
				chooseButton:function(){
					"step 0"
					if(typeof event.dialog=='number'){
						event.dialog=get.idDialog(event.dialog);
					}
					if(event.createDialog&&!event.dialog){
						if(Array.isArray(event.createDialog)){
							event.createDialog.add('hidden');
							event.dialog=ui.create.dialog.apply(this,event.createDialog);
						}
						event.closeDialog=true;
					}
					if(event.dialog==undefined) event.dialog=ui.dialog;
					if(event.isMine()||event.dialogdisplay){
						event.dialog.style.display='';
						event.dialog.open();
					}
					var filterButton=event.filterButton||function(){return true};
					var selectButton=get.select(event.selectButton);
					var buttons=event.dialog.buttons;
					var buttonsx=[];
					var num=0;
					for(var i=0;i<buttons.length;i++){
						var button=buttons[i];
						if(filterButton(button,player)){
							num++;
							buttonsx.add(button);
						}
					}
					if(event.isMine()){
						if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
							ui.click.cancel();
							return;
						}
						else if(event.direct&&num==selectButton[0]||event.forceDirect){
							var buttons=buttonsx.slice(0,num);
							event.result={
								bool:true,
								button:[buttons],
								links:get.links(buttons),
							};
							event.dialog.close();
						}
						else{
							game.check();
							game.pause();
						}
					}
					else if(event.isOnline()){
						if(event.direct&&num==1||event.forceDirect){
							var buttons=buttonsx.slice(0,num);
							event.result={
								bool:true,
								button:[buttons],
								links:get.links(buttons),
							};
							event.dialog.close();
						}
						else{
							event.send();
						}
						delete event.callback;
					}
					else{
						event.result='ai';
					}
					if(event.onfree){
						lib.init.onfree();
					}
					"step 1"
					if(event.result=='ai'){
						if(event.processAI){
							event.result=event.processAI();
						}
						else{
							game.check();
							if((ai.basic.chooseButton(event.ai)||forced)&&(!event.filterOk||event.filterOk())) ui.click.ok();
							else ui.click.cancel();
						}
					}
					if(event.closeDialog){
						event.dialog.close();
					}
					if(event.callback){
						event.callback(event.player,event.result);
					}
					event.resume();
				},
				chooseCardOL:function(){
					'step 0'
					event.targets=event.list.slice(0);
					if(!_status.connectMode){
						event.result=[];
						event.goto(7);
					}
					else{
						for(var i=0;i<event.list.length;i++){
							var target=event.list[i];
							target.wait();
							if(target.isOnline()){
								target.send(function(args,set){
									game.me.chooseCard.apply(game.me,args).set(set);
									game.resume();
								},event._args,event._set);
								event.list.splice(i--,1);
							}
							else if(target==game.me){
								event.withme=true;
								event.list.splice(i--,1);
							}
						}
					}
					'step 1'
					if(event.list.length){
						event.target=event.list.shift();
						event.target.chooseCard.apply(event.target,event._args).set(event._set);
					}
					else{
						event.goto(3);
					}
					'step 2'
					event.target.unwait(result);
					event.goto(1);
					'step 3'
					if(event.withme){
						game.me.chooseCard.apply(game.me,event._args).set(event._set);
					}
					else{
						event.goto(5);
					}
					'step 4'
					game.me.unwait(result);
					'step 5'
					if(!event.resultOL){
						game.pause();
					}
					'step 6'
					event.result=[];
					for(var i=0;i<event.targets.length;i++){
						event.result[i]=event.resultOL[event.targets[i].playerid]||{};
						if(event.result[i]=='ai'&&event.aiCard){
							event.result[i]=event.aiCard(event.targets[i]);
						}
					}
					event.finish();
					'step 7'
					if(event.list.length){
						event.target=event.list.shift();
						event.target.chooseCard.apply(event.target,event._args).set(event._set);
					}
					else{
						for(var i=0;i<event.targets.length;i++){
							if(!event.result[i]){
								event.result[i]={};
							}
						}
						event.finish();
					}
					'step 8'
					event.result[event.targets.indexOf(event.target)]=result;
					event.goto(7);
				},
				chooseButtonOL:function(){
					'step 0'
					//ui.arena.classList.add('markhidden');
					for(var i=0;i<event.list.length;i++){
						var current=event.list[i];
						current[0].wait();
						if(current[0].isOnline()){
							var target=current.shift();
							target.send(function(args,callback,switchToAuto,processAI){
								//ui.arena.classList.add('markhidden');
								var next=game.me.chooseButton.apply(game.me,args);
								next.callback=callback;
								next.switchToAuto=switchToAuto;
								next.processAI=processAI;
								next.complexSelect=true;
								game.resume();
							},current,event.callback,event.switchToAuto,event.processAI);
							target._choose_button_ol=current;
							event.list.splice(i--,1);
						}
						else if(current[0]==game.me){
							event.last=current;
							event.last.shift();
							event.list.splice(i--,1);
						}
					}
					'step 1'
					if(event.list.length){
						var current=event.list.shift();
						event.target=current.shift();
						var next=event.target.chooseButton.apply(event.target,current);
						next.callback=event.callback;
						next.switchToAuto=event.switchToAuto;
						next.processAI=event.processAI;
					}
					else{
						event.goto(3);
					}
					'step 2'
					event.target.unwait(result);
					event.goto(1);
					'step 3'
					if(event.last){
						var next=game.me.chooseButton.apply(game.me,event.last);
						next.callback=event.callback;
						next.switchToAuto=event.switchToAuto;
						next.processAI=event.processAI;
					}
					else{
						event.goto(5);
					}
					'step 4'
					game.me.unwait(result);
					'step 5'
					if(!event.resultOL){
						game.pause();
					}
					'step 6'
					/*game.broadcastAll(function(){
						ui.arena.classList.remove('markhidden');
					});*/
					event.result=event.resultOL;
				},
				chooseCard:function(){
					"step 0"
					if(event.directresult){
						event.result={
							buttons:[],
							cards:event.directresult.slice(0),
							targets:[],
							confirm:'ok',
							bool:true,
							links:[]
						};
					}
					else{
						if(event.isMine()){
							game.check();
							game.pause();
							if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
								ui.click.cancel();
								return;
							}
							if(event.prompt!=false){
								var str;
								if(typeof event.prompt=='string') str=event.prompt;
								else{
									str='请选择'
									var range=get.select(event.selectCard);
									if(range[0]==range[1]) str+=get.cnNumber(range[0]);
									else if(range[1]==Infinity) str+='至少'+get.cnNumber(range[0]);
									else str+=get.cnNumber(range[0])+'至'+get.cnNumber(range[1]);
									str+='张';
									if(event.position=='h'||event.position==undefined) str+='手';
									if(event.position=='e') str+='装备';
									str+='牌';
								}
								event.dialog=ui.create.dialog(str);
								if(event.prompt2){
									event.dialog.addText(event.prompt2,event.prompt2.length<=20);
								}
								if(Array.isArray(event.promptx)){
									for(var i=0;i<event.promptx.length;i++){
										event.dialog.add(event.promptx[i]);
									}
								}
								if(Array.isArray(event.selectCard)){
									event.promptbar=event.dialog.add('0/'+get.numStr(event.selectCard[1],'card'));
									event.custom.add.card=function(){
										_status.event.promptbar.innerHTML=
										ui.selected.cards.length+'/'+get.numStr(_status.event.selectCard[1],'card');
									}
								}
							}
						}
						else if(event.isOnline()){
							event.send();
						}
						else{
							event.result='ai';
						}
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if((ai.basic.chooseCard(event.ai)||forced)&&(!event.filterOk||event.filterOk())){
							ui.click.ok();
						}
						else if(event.skill){
							var skill=event.skill;
							ui.click.cancel();
							event._aiexclude.add(skill);
							event.redo();
							game.resume();
						}
						else{
							ui.click.cancel();
						}
					}
					"step 2"
					event.resume();
					if(event.glow_result&&event.result.cards&&!event.directresult){
						for(var i=0;i<event.result.cards.length;i++){
							event.result.cards[i].classList.add('glow');
						}
					}
					if(event.dialog) event.dialog.close();
				},
				chooseTarget:function(){
					"step 0"
					if(event.isMine()){
						if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
							ui.click.cancel();
							return;
						}
						game.check();
						game.pause();
						if(event.createDialog&&!event.dialog&&Array.isArray(event.createDialog)){
							event.dialog=ui.create.dialog.apply(this,event.createDialog);
						}
						else if(event.prompt!=false){
							var str;
							if(typeof event.prompt=='string') str=event.prompt;
							else{
								str='请选择'
								var range=get.select(event.selectTarget);
								if(range[0]==range[1]) str+=get.cnNumber(range[0]);
								else if(range[1]==Infinity) str+='至少'+get.cnNumber(range[0]);
								else str+=get.cnNumber(range[0])+'至'+get.cnNumber(range[1]);
								str+='个目标';
							}
							event.dialog=ui.create.dialog(str);
							if(event.prompt2){
								event.dialog.addText(event.prompt2,event.prompt2.length<=20);
							}
							if(event.promptbar!='none'){
								event.promptbar=event.dialog.add('0/'+get.numStr(get.select(event.selectTarget)[1],'target'));
								event.custom.add.target=function(){
									_status.event.promptbar.innerHTML=
									ui.selected.targets.length+'/'+get.numStr(get.select(event.selectTarget)[1],'target');
								}
							}
						}
						else if(get.itemtype(event.dialog)=='dialog'){
							event.dialog.open();
						}
					}
					else if(event.isOnline()){
						event.send();
					}
					else{
						event.result='ai';
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if((ai.basic.chooseTarget(event.ai)||forced)&&(!event.filterOk||event.filterOk())){
							ui.click.ok();
						}
						else{
							ui.click.cancel();
						}
					}
					if(event.result.bool&&event.animate!==false){
						for(var i=0;i<event.result.targets.length;i++){
							event.result.targets[i].animate('target');
						}
					}
					if(event.dialog) event.dialog.close();
					event.resume();
					"step 2"
					if(event.onresult){
						event.onresult(event.result);
					}
					if(event.result.bool&&event.autodelay&&!event.isMine()){
						if(typeof event.autodelay=='number'){
							game.delayx(event.autodelay);
						}
						else{
							game.delayx();
						}
					}
				},
				chooseCardTarget:function(){
					"step 0"
					if(event.isMine()){
						if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
							ui.click.cancel();
							return;
						}
						game.check();
						game.pause();
						if(event.prompt!=false){
							event.dialog=ui.create.dialog(event.prompt||'请选择卡牌和目标');
							if(event.prompt2){
								event.dialog.addText(event.prompt2,event.prompt2.length<=20);
							}
						}
					}
					else if(event.isOnline()){
						event.send();
					}
					else{
						event.result='ai';
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if(ai.basic.chooseCard(event.ai1)||forced){
							if((ai.basic.chooseTarget(event.ai2)||forced)&&(!event.filterOk||event.filterOk())){
								ui.click.ok();
								_status.event._aiexclude.length=0;
							}
							else{
								ui.click.cancel();
							}
						}
						else{
							ui.click.cancel();
						}
					}
					"step 2"
					event.resume();
					if(event.result.bool&&event.animate!==false){
						for(var i=0;i<event.result.targets.length;i++){
							event.result.targets[i].animate('target');
						}
					}
					if(event.dialog) event.dialog.close();
				},
				chooseControl:function(){
					"step 0"
					if(event.controls.length==0){
						if(event.sortcard){
							var sortnum=2;
							if(event.sorttop){
								sortnum=1;
							}
							for(var i=0;i<event.sortcard.length+sortnum;i++){
								event.controls.push(get.cnNumber(i,true));
							}
						}
						else if(event.choiceList){
							for(var i=0;i<event.choiceList.length;i++){
								event.controls.push('选项'+get.cnNumber(i+1,true));
							}
						}
						else{
							event.finish();
							return;
						}
					}
					else if(event.choiceList&&event.controls.length==1&&event.controls[0]=='cancel2'){
						event.controls.shift();
						for(var i=0;i<event.choiceList.length;i++){
							event.controls.push('选项'+get.cnNumber(i+1,true));
						}
						event.controls.push('cancel2');
					}
					if(event.isMine()){
						if(event.arrangeSkill){
							var hidden=player.hiddenSkills.slice(0);
							game.expandSkills(hidden);
							if(hidden.length){
								for(var i of event.controls){
									if(_status.prehidden_skills.contains(i)&&hidden.contains(i)){
										event.result={
											bool:true,
											control:i,
										}
										return;
									}
								}
							}
						}
						else if(event.hsskill&&_status.prehidden_skills.contains(event.hsskill)&&event.controls.contains('cancel2')){
							event.result={
								bool:true,
								control:'cancel2',
							}
							return;
						}
						if(event.sortcard){
							var prompt=event.prompt||'选择一个位置';
							if(event.tosort){
								prompt+='放置'+get.translation(event.tosort);
							}
							event.dialog=ui.create.dialog(prompt,'hidden');
							if(event.sortcard&&event.sortcard.length){
								event.dialog.addSmall(event.sortcard);
							}
							else{
								event.dialog.buttons=[];
								event.dialog.add(ui.create.div('.buttons'));
							}
							var buttons=event.dialog.content.lastChild;
							var sortnum=2;
							if(event.sorttop){
								sortnum=1;
							}
							for(var i=0;i<event.dialog.buttons.length+sortnum;i++){
								var item=ui.create.div('.button.card.pointerdiv.mebg');
								item.style.width='50px';
								buttons.insertBefore(item,event.dialog.buttons[i]);
								item.innerHTML='<div style="font-family: xinwei;font-size: 25px;height: 75px;line-height: 25px;top: 8px;left: 10px;width: 30px;">第'+get.cnNumber(i+1,true)+'张</div>';
								if(i==event.dialog.buttons.length+1){
									item.firstChild.innerHTML='牌堆底';
								}
								item.link=get.cnNumber(i,true);
								item.listen(ui.click.dialogcontrol);
							}

							event.dialog.forcebutton=true;
							event.dialog.classList.add('forcebutton');
							event.dialog.open();
						}
						else if(event.dialogcontrol){
							event.dialog=ui.create.dialog(event.prompt||'选择一项','hidden');
							for(var i=0;i<event.controls.length;i++){
								var item=event.dialog.add('<div class="popup text pointerdiv" style="width:calc(100% - 10px);display:inline-block">'+event.controls[i]+'</div>');
								item.firstChild.listen(ui.click.dialogcontrol);
								item.firstChild.link=event.controls[i];
							}
							event.dialog.forcebutton=true;
							event.dialog.classList.add('forcebutton');
							if(event.addDialog){
								for(var i=0;i<event.addDialog.length;i++){
									if(get.itemtype(event.addDialog[i])=='cards'){
										event.dialog.addSmall(event.addDialog[i]);
									}
									else{
										event.dialog.add(event.addDialog[i]);
									}
								}
								event.dialog.add(ui.create.div('.placeholder.slim'));
							}
							event.dialog.open();
						}
						else{
							if(event.seperate||lib.config.seperate_control){
								var controls=event.controls.slice(0);
								var num=0;
								controls.remove('cancel2');
								if(event.direct&&controls.length==1||event.forceDirect){
									event.result={
										control:event.controls[0].link,
										links:get.links([event.controls[0]]),
									};
									return;
								}
								else{
									event.controlbars=[];
									for(var i=0;i<event.controls.length;i++){
										event.controlbars.push(ui.create.control([event.controls[i]]));
									}
								}
							}
							else{
								var controls=event.controls.slice(0);
								var num=0;
								controls.remove('cancel2');
								if(event.direct&&controls.length==1||event.forceDirect){
									event.result={
										control:event.controls[0].link,
										links:get.links([event.controls[0]]),
									};
									return;
								}
								event.controlbar=ui.create.control(event.controls);
							}
							if(event.dialog){
								if(Array.isArray(event.dialog)){
									event.dialog=ui.create.dialog.apply(this,event.dialog);
								}
								event.dialog.open();
							}
							else if(event.choiceList){
								event.dialog=ui.create.dialog(event.prompt||'选择一项','hidden');
								event.dialog.forcebutton=true;
								event.dialog.open();
								for(var i=0;i<event.choiceList.length;i++){
									event.dialog.add('<div class="popup text" style="width:calc(100% - 10px);display:inline-block">'+
									(event.displayIndex!==false?('选项'+get.cnNumber(i+1,true)+':'):'')+event.choiceList[i]+'</div>');
								}
							}
							else if(event.prompt){
								event.dialog=ui.create.dialog(event.prompt);
								if(event.prompt2){
									event.dialog.addText(event.prompt2,Boolean(event.prompt2.length<=20||event.centerprompt2));
								}
							}
						}
						game.pause();
						game.countChoose();
						event.choosing=true;
					}
					else if(event.isOnline()){
						event.send();
					}
					else{
						event.result='ai';
					}
					"step 1"
					if(event.result=='ai'){
						event.result={};
						if(event.ai){
							var result=event.ai(event.getParent(),player);
							if(typeof result=='number') event.result.control=event.controls[result];
							else event.result.control=result;
						}
						else event.result.control=event.controls[event.choice];
					}
					event.result.index=event.controls.indexOf(event.result.control);
					event.choosing=false;
					_status.imchoosing=false;
					if(event.dialog&&event.dialog.close) event.dialog.close();
					if(event.controlbar) event.controlbar.close();
					if(event.controlbars){
						for(var i=0;i<event.controlbars.length;i++){
							event.controlbars[i].close();
						}
					}
					event.resume();
				},
				chooseBool:function(){
					"step 0"
					if(event.isMine()){
						if(event.frequentSkill&&!lib.config.autoskilllist.contains(event.frequentSkill)){
							ui.click.ok();
							return;
						}
						else if(event.hsskill&&_status.prehidden_skills.contains(event.hsskill)){
							ui.click.cancel();
							return;
						}
						ui.create.confirm('oc');
						if(event.createDialog&&!event.dialog){
							if(Array.isArray(event.createDialog)){
								event.dialog=ui.create.dialog.apply(this,event.createDialog);
								if(event.dialogselectx){
									for(var i=0;i<event.dialog.buttons.length;i++){
										event.dialog.buttons[i].classList.add('selectedx');
									}
								}
							}
						}
						if(event.dialog){
							event.dialog.open();
						}
						else if(event.prompt){
							event.dialog=ui.create.dialog(event.prompt);
							if(event.prompt2){
								event.dialog.addText(event.prompt2,event.prompt2.length<=20);
							}
						}
						game.pause();
						game.countChoose();
						event.choosing=true;
					}
					else if(event.isOnline()){
						event.send();
					}
					else{
						event.result='ai';
					}
					"step 1"
					if(event.result=='ai'){
						if(event.ai){
							event.choice=event.ai(event.getParent(),player);
						}
						event.result={bool:event.choice};
					}
					_status.imchoosing=false;
					event.choosing=false;
					if(event.dialog) event.dialog.close();
					event.resume();
				},
				chooseDrawRecover:function(){
					'step 0'
					if(player.isHealthy()&&event.forced){
						player.draw(event.num1);
						event.finish();
						return;
					}
					var controls=['draw_card'];
					if(player.isDamaged()){
						event.num2=Math.min(event.num2,player.maxHp-player.hp);
						controls.push('recover_hp');
					}
					if(!event.forced){
						controls.push('cancel2');
					}
					var prompt=event.prompt;
					if(!prompt){
						if(player.isHealthy()){
							prompt='是否摸'+get.cnNumber(event.num1)+'张牌?';
						}
						else{
							prompt='摸'+get.cnNumber(event.num1)+'张牌或回复'+get.cnNumber(event.num2)+'点体力';
						}
					}
					var next=player.chooseControl(controls);
					next.set('prompt',prompt);
					if(event.hsskill) next.setHiddenSkill(event.hsskill);
					if(event.ai){
						next.set('ai',event.ai);
					}
					else{
						var choice;
						if(player.isDamaged()&&get.recoverEffect(player)>0&&(
							player.hp==1||player.needsToDiscard()||
							player.hasSkillTag('maixie_hp')||event.num2>event.num1||
							(event.num2==event.num1&&player.needsToDiscard(1))
						)){
							choice='recover_hp';
						}
						else{
							choice='draw_card';
						}
						next.set('ai',function(){
							return _status.event.choice;
						});
						next.set('choice',choice);
					}
					'step 1'
					if(result.control!='cancel2'){
						if(event.logSkill){
							if(typeof event.logSkill=='string'){
								player.logSkill(event.logSkill);
							}
							else if(Array.isArray(event.logSkill)){
								player.logSkill.apply(player,event.logSkill);
							}
						}
						if(result.control=='draw_card'){
							player.draw(event.num1);
						}
						else{
							player.recover(event.num2);
						}
					}
					event.result=result;
				},
				choosePlayerCard:function(){
					"step 0"
					if(!event.dialog) event.dialog=ui.create.dialog('hidden');
					else if(!event.isMine()){
						event.dialog.style.display='none';
					}
					if(event.prompt){
						event.dialog.add(event.prompt);
					}
					else{
						event.dialog.add('选择'+get.translation(target)+'的一张牌');
					}
					if(event.prompt2){
						event.dialog.addText(event.prompt2);
					}
					var expand_length=0;
					var directh=!lib.config.unauto_choose;
					for(var i=0;i<event.position.length;i++){
						if(event.position[i]=='h'){
							var hs=target.getCards('h');
							if(hs.length){
								expand_length+=Math.ceil(hs.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">手牌区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								hs.randomSort();
								if(event.visible||target.isUnderControl(true)||player.hasSkillTag('viewHandcard',null,target,true)){
									event.dialog.add(hs);
									directh=false;
								}
								else{
									var shown=hs.filter(card=>get.is.shownCard(card));
									if(shown.length){
										var hidden=hs.filter(card=>!shown.includes(card));
										var buttons=ui.create.div('.buttons',event.dialog.content);
										event.dialog.buttons=event.dialog.buttons.concat(ui.create.buttons(shown,'card',buttons));
										event.dialog.buttons=event.dialog.buttons.concat(ui.create.buttons(hidden,'blank',buttons));
										if(event.dialog.forcebutton!==false) event.dialog.forcebutton=true;
										if(event.dialog.buttons.length>3){
											event.dialog.classList.remove('forcebutton-auto');
										}
										else if(!event.dialog.noforcebutton){
											event.dialog.classList.add('forcebutton-auto');
										}
									}
									else{
										event.dialog.add([hs,'blank']);
									}
								}
							}
						}
						else if(event.position[i]=='e'){
							var es=target.getCards('e');
							if(es.length){
								expand_length+=Math.ceil(es.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">装备区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								event.dialog.add(es);
								directh=false;
							}
						}
						else if(event.position[i]=='j'){
							var js=target.getCards('j');
							if(js.length){
								expand_length+=Math.ceil(js.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">判定区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								event.dialog.add(js);
								directh=false;
							}
						}
					}
					if(event.dialog.buttons.length==0){
						event.finish();
						return;
					}
					var cs=target.getCards(event.position);
					var select=get.select(event.selectButton);
					if(event.forced&&select[0]>=cs.length){
						event.result={
							bool:true,
							buttons:event.dialog.buttons,
							links:cs
						}
					}
					else if(event.forced&&directh&&!event.isOnline()&&select[0]==select[1]){
						event.result={
							bool:true,
							buttons:event.dialog.buttons.randomGets(select[0]),
							links:[]
						}
						for(var i=0;i<event.result.buttons.length;i++){
							event.result.links[i]=event.result.buttons[i].link;
						}
					}
					else{
						if(event.isMine()){
							if(event.hsskill&&!event.forced&&_status.prehidden_skills.contains(event.hsskill)){
								ui.click.cancel();
								return;
							}
							event.dialog.open();
							game.check();
							game.pause();
							if(expand_length>2){
								ui.arena.classList.add('choose-player-card');
								event.dialog.classList.add('fullheight');
							}
						}
						else if(event.isOnline()){
							event.send();
						}
						else{
							event.result='ai';
						}
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if((ai.basic.chooseButton(event.ai)||forced)&&(!event.filterOk||event.filterOk())) ui.click.ok();
						else ui.click.cancel();
					}
					event.dialog.close();
					if(event.result.links){
						event.result.cards=event.result.links.slice(0);
					}
					event.resume();
					setTimeout(function(){
						ui.arena.classList.remove('choose-player-card');
					},500);
				},
				discardPlayerCard:function(){
					"step 0"
					if(event.directresult){
						event.result={
							buttons:[],
							cards:event.directresult.slice(0),
							links:event.directresult.slice(0),
							targets:[],
							confirm:'ok',
							bool:true
						};
						event.cards=event.directresult.slice(0);
						event.goto(2);
						return;
					}
					if(!event.dialog) event.dialog=ui.create.dialog('hidden');
					else if(!event.isMine()){
						event.dialog.style.display='none';
					}
					if(event.prompt==undefined){
						var str='弃置'+get.translation(target);
						var range=get.select(event.selectButton);
						if(range[0]==range[1]) str+=get.cnNumber(range[0]);
						else if(range[1]==Infinity) str+='至少'+get.cnNumber(range[0]);
						else str+=get.cnNumber(range[0])+'至'+get.cnNumber(range[1]);
						str+='张';
						if(event.position=='h'||event.position==undefined) str+='手';
						if(event.position=='e') str+='装备';
						str+='牌';
						event.prompt=str;
					}
					if(event.prompt){
						event.dialog.add(event.prompt);
					}
					if(event.prompt2){
						event.dialog.addText(event.prompt2);
					}
					var directh=(!lib.config.unauto_choose&&!event.complexSelect);
					var expand_length=0;
					for(var i=0;i<event.position.length;i++){
						if(event.position[i]=='h'){
							var hs=target.getDiscardableCards(player,'h');
							expand_length+=Math.ceil(hs.length/6);
							if(hs.length){
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">手牌区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								hs.randomSort();
								if(event.visible||target.isUnderControl(true)||player.hasSkillTag('viewHandcard',null,target,true)){
									event.dialog.add(hs);
									directh=false;
								}
								else{
									var shown=hs.filter(card=>get.is.shownCard(card));
									if(shown.length){
										var hidden=hs.filter(card=>!shown.includes(card));
										var buttons=ui.create.div('.buttons',event.dialog.content);
										event.dialog.buttons=event.dialog.buttons.concat(ui.create.buttons(shown,'card',buttons));
										event.dialog.buttons=event.dialog.buttons.concat(ui.create.buttons(hidden,'blank',buttons));
										if(event.dialog.forcebutton!==false) event.dialog.forcebutton=true;
										if(event.dialog.buttons.length>3){
											event.dialog.classList.remove('forcebutton-auto');
										}
										else if(!event.dialog.noforcebutton){
											event.dialog.classList.add('forcebutton-auto');
										}
									}
									else{
										event.dialog.add([hs,'blank']);
									}
								}
							}
						}
						else if(event.position[i]=='e'){
							var es=target.getDiscardableCards(player,'e');
							if(es.length){
								expand_length+=Math.ceil(es.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">装备区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								event.dialog.add(es);
								directh=false;
							}
						}
						else if(event.position[i]=='j'){
							var js=target.getDiscardableCards(player,'j');
							if(js.length){
								expand_length+=Math.ceil(js.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">判定区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								event.dialog.add(js);
								directh=false;
							}
						}
					}
					if(event.dialog.buttons.length==0){
						event.finish();
						return;
					}
					var cs=target.getCards(event.position);
					var select=get.select(event.selectButton);
					if(event.forced&&select[0]>=cs.length){
						event.result={
							bool:true,
							buttons:event.dialog.buttons,
							links:cs
						}
					}
					else if(event.forced&&directh&&!event.isOnline()&&select[0]==select[1]){
						event.result={
							bool:true,
							buttons:event.dialog.buttons.randomGets(select[0]),
							links:[]
						}
						for(var i=0;i<event.result.buttons.length;i++){
							event.result.links[i]=event.result.buttons[i].link;
						}
					}
					else{
						if(event.isMine()){
							event.dialog.open();
							game.check();
							game.pause();
							if(expand_length>2){
								ui.arena.classList.add('discard-player-card');
								event.dialog.classList.add('fullheight');
							}
						}
						else if(event.isOnline()){
							event.send();
						}
						else{
							event.result='ai';
						}
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if((ai.basic.chooseButton(event.ai)||forced)&&(!event.filterOk||event.filterOk())) ui.click.ok();
						else ui.click.cancel();
					}
					event.dialog.close();
					"step 2"
					event.resume();
					setTimeout(function(){
						ui.arena.classList.remove('discard-player-card');
					},500);
					if(event.result.bool&&event.result.links&&!game.online){
						if(event.logSkill){
							if(typeof event.logSkill=='string'){
								player.logSkill(event.logSkill);
							}
							else if(Array.isArray(event.logSkill)){
								player.logSkill.apply(player,event.logSkill);
							}
						}
						var cards=[];
						for(var i=0;i<event.result.links.length;i++){
							cards.push(event.result.links[i]);
						}
						event.result.cards=event.result.links.slice(0);
						event.cards=cards;
						event.trigger("rewriteDiscardResult");
					}
					"step 3"
					if(event.boolline){
						player.line(target,'green');
					}
					if(!event.chooseonly){
						var next=target.discard(event.cards);
						if(player!=target) next.notBySelf=true;
						next.discarder=player;
						event.done=next;
						if(event.delay===false){
							next.set('delay',false);
						}
					}
				},
				gainPlayerCard:function(){
					"step 0"
					if(event.directresult){
						event.result={
							buttons:[],
							cards:event.directresult.slice(0),
							links:event.directresult.slice(0),
							targets:[],
							confirm:'ok',
							bool:true
						};
						event.cards=event.directresult.slice(0);
						event.goto(2);
						return;
					}
					if(!event.dialog) event.dialog=ui.create.dialog('hidden');
					else if(!event.isMine()){
						event.dialog.style.display='none';
					}
					if(event.prompt==undefined){
						var str='获得'+get.translation(target);
						var range=get.select(event.selectButton);
						if(range[0]==range[1]) str+=get.cnNumber(range[0]);
						else if(range[1]==Infinity) str+='至少'+get.cnNumber(range[0]);
						else str+=get.cnNumber(range[0])+'至'+get.cnNumber(range[1]);
						str+='张';
						if(event.position=='h'||event.position==undefined) str+='手';
						if(event.position=='e') str+='装备';
						str+='牌';
						event.prompt=str;
					}
					if(event.prompt){
						event.dialog.add(event.prompt);
					}
					if(event.prompt2){
						event.dialog.addText(event.prompt2);
					}
					var expand_length=0;
					var directh=(!lib.config.unauto_choose&&!event.complexSelect);
					for(var i=0;i<event.position.length;i++){
						if(event.position[i]=='h'){
							var hs=target.getGainableCards(player,'h');
							if(hs.length){
								expand_length+=Math.ceil(hs.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">手牌区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								hs.randomSort();
								if(event.visible||target.isUnderControl(true)||player.hasSkillTag('viewHandcard',null,target,true)){
									event.dialog.add(hs);
									directh=false;
								}
								else{
									var shown=hs.filter(card=>get.is.shownCard(card));
									if(shown.length){
										var hidden=hs.filter(card=>!shown.includes(card));
										var buttons=ui.create.div('.buttons',event.dialog.content);
										event.dialog.buttons=event.dialog.buttons.concat(ui.create.buttons(shown,'card',buttons));
										event.dialog.buttons=event.dialog.buttons.concat(ui.create.buttons(hidden,'blank',buttons));
										if(event.dialog.forcebutton!==false) event.dialog.forcebutton=true;
										if(event.dialog.buttons.length>3){
											event.dialog.classList.remove('forcebutton-auto');
										}
										else if(!event.dialog.noforcebutton){
											event.dialog.classList.add('forcebutton-auto');
										}
									}
									else{
										event.dialog.add([hs,'blank']);
									}
								}
							}
						}
						else if(event.position[i]=='e'){
							var es=target.getGainableCards(player,'e');
							if(es.length){
								expand_length+=Math.ceil(es.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">装备区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								event.dialog.add(es);
								directh=false;
							}
						}
						else if(event.position[i]=='j'){
							var js=target.getGainableCards(player,'j');
							if(js.length){
								expand_length+=Math.ceil(js.length/6);
								var title=event.dialog.add('<div class="text center" style="margin: 0px;">判定区</div>');
								title.style.margin='0px';
								title.style.padding='0px';
								event.dialog.add(js);
								directh=false;
							}
						}
					}
					if(event.dialog.buttons.length==0){
						event.dialog.close();
						event.finish();
						return;
					}
					var cs=target.getCards(event.position);
					var select=get.select(event.selectButton);
					if(event.forced&&select[0]>=cs.length){
						event.result={
							bool:true,
							buttons:event.dialog.buttons,
							links:cs
						}
					}
					else if(event.forced&&directh&&!event.isOnline()&&select[0]==select[1]){
						event.result={
							bool:true,
							buttons:event.dialog.buttons.randomGets(select[0]),
							links:[]
						}
						for(var i=0;i<event.result.buttons.length;i++){
							event.result.links[i]=event.result.buttons[i].link;
						}
					}
					else{
						if(event.isMine()){
							event.dialog.open();
							game.check();
							game.pause();
							if(expand_length>2){
								ui.arena.classList.add('gain-player-card');
								event.dialog.classList.add('fullheight');
							}
						}
						else if(event.isOnline()){
							event.send();
						}
						else{
							event.result='ai';
						}
					}
					"step 1"
					if(event.result=='ai'){
						game.check();
						if((ai.basic.chooseButton(event.ai)||forced)&&(!event.filterOk||event.filterOk())) ui.click.ok();
						else ui.click.cancel();
					}
					event.dialog.close();
					"step 2"
					event.resume();
					setTimeout(function(){
						ui.arena.classList.remove('gain-player-card');
					},500);
					if(game.online||!event.result.bool){
						event.finish();
					}
					"step 3"
					if(event.logSkill&&event.result.bool&&!game.online){
						if(typeof event.logSkill=='string'){
							player.logSkill(event.logSkill);
						}
						else if(Array.isArray(event.logSkill)){
							player.logSkill.apply(player,event.logSkill);
						}
					}
					var cards=[];
					for(var i=0;i<event.result.links.length;i++){
						cards.push(event.result.links[i]);
					}
					event.result.cards=event.result.links.slice(0);
					event.cards=cards;
					event.trigger("rewriteGainResult");
					"step 4"
					if(event.boolline){
						player.line(target,'green');
					}
					if(!event.chooseonly){
						if(event.delay!==false){
							var next=player.gain(event.cards,target,event.visibleMove?'give':'giveAuto','bySelf');
							event.done=next;
						}
						else{
							var next=player.gain(event.cards,target,'bySelf');
							event.done=next;
							target[event.visibleMove?'$give':'$giveAuto'](cards,player);
							if(event.visibleMove) next.visible=true;
						}
					}
					else target[event.visibleMove?'$give':'$giveAuto'](cards,player);
				},
				showHandcards:function(){
					"step 0"
					if(player.countCards('h')==0){
						event.finish();
						return;
					}
					var cards=player.getCards('h');
					player.showCards(cards).setContent(function(){});
					var str=get.translation(player.name)+'的手牌';
					if(typeof event.prompt=='string'){
						str=event.prompt;
					}
					event.dialog=ui.create.dialog(str,cards);
					event.dialogid=lib.status.videoId++;
					event.dialog.videoId=event.dialogid;
					game.broadcast(function(str,cards,id){
						ui.create.dialog(str,cards).videoId=id;
					},str,cards,event.dialogid);
					game.log(player,'展示了',cards);
					game.addVideo('showCards',player,[str,get.cardsInfo(cards)]);
					game.delayx(2);
					"step 1"
					game.broadcast('closeDialog',event.dialogid);
					event.dialog.close();
				},
				showCards:function(){
					"step 0"
					if(get.itemtype(cards)!='cards'){
						event.finish();
						return;
					}
					if(!event.str){
						event.str=get.translation(player.name)+'展示的牌';
					}
					event.dialog=ui.create.dialog(event.str,cards);
					event.dialogid=lib.status.videoId++;
					event.dialog.videoId=event.dialogid;

					if(event.hiddencards){
						for(var i=0;i<event.dialog.buttons.length;i++){
							if(event.hiddencards.contains(event.dialog.buttons[i].link)){
								event.dialog.buttons[i].className='button card';
								event.dialog.buttons[i].innerHTML='';
							}
						}
					}
					game.broadcast(function(str,cards,cards2,id){
						var dialog=ui.create.dialog(str,cards);
						dialog.forcebutton=true;
						dialog.videoId=id;
						if(cards2){
							for(var i=0;i<dialog.buttons.length;i++){
								if(cards2.contains(dialog.buttons[i].link)){
									dialog.buttons[i].className='button card';
									dialog.buttons[i].innerHTML='';
								}
							}
						}
					},event.str,cards,event.hiddencards,event.dialogid);
					if(event.hiddencards){
						var cards2=cards.slice(0);
						for(var i=0;i<event.hiddencards.length;i++){
							cards2.remove(event.hiddencards[i]);
						}
						game.log(player,'展示了',cards2);
					}
					else{
						game.log(player,'展示了',cards);
					}
					game.delayx(event.delay_time||2.5);
					game.addVideo('showCards',player,[event.str,get.cardsInfo(cards)]);
					"step 1"
					game.broadcast('closeDialog',event.dialogid);
					event.dialog.close();
				},
				viewCards:function(){
					"step 0"
					if(player==game.me){
						event.dialog=ui.create.dialog(event.str,event.cards);
						if(event.isMine()){
							game.pause();
							ui.create.confirm('o');
							game.countChoose();
							event.choosing=true;
						}
						else{
							event.finish();
							event.result='viewed';
							setTimeout(function(){
								event.dialog.close();
							},2*lib.config.duration);
							game.delayx(2);
						}
					}
					else if(event.isOnline()){
						event.send();
					}
					else{
						event.finish();
					}
					"step 1"
					event.result='viewed';
					_status.imchoosing=false;
					event.choosing=false;
					if(event.dialog) event.dialog.close();
				},
				moveCard:function(){
					'step 0'
					if(!player.canMoveCard(null,event.nojudge)){
						event.finish();
						return;
					}
					var next=player.chooseTarget(2,function(card,player,target){
						if(ui.selected.targets.length){
							var from=ui.selected.targets[0];
							var js=from.getCards('j');
							for(var i=0;i<js.length;i++){
								if(_status.event.nojudge) break;
								if(target.canAddJudge(js[i])) return true;
							}
							if(target.isMin()) return false;
							var es=from.getCards('e');
							for(var i=0;i<es.length;i++){
								if(target.canEquip(es[i])) return true;
							}
							return false;
						}
						else{
							var range='ej';
							if(_status.event.nojudge) range='e';
							return target.countCards(range)>0;
						}
					});
					next.set('nojudge',event.nojudge||false);
					next.set('ai',function(target){
						var player=_status.event.player;
						var att=get.attitude(player,target);
						var sgnatt=get.sgn(att);
						if(ui.selected.targets.length==0){
							if(att>0){
								if(!_status.event.nojudge&&target.countCards('j',function(card){
									return game.hasPlayer(function(current){
										return current!=target&&current.canAddJudge(card)&&get.attitude(player,current)<0;
									})
								})) return 14;
								if(target.countCards('e',function(card){
									return get.value(card,target)<0&&game.hasPlayer(function(current){
										return current!=target&&get.attitude(player,current)<0&&current.canEquip(card)&&get.effect(target,card,player,player)<0;
									});
								})>0) return 9;
							}
							else if(att<0){
								if(game.hasPlayer(function(current){
									if(current!=target&&get.attitude(player,current)>0){
										var es=target.getCards('e');
										for(var i=0;i<es.length;i++){
											if(get.value(es[i],target)>0&&current.canEquip(es[i])&&get.effect(current,es[i],player,player)>0) return true;
										}
									}
								})){
									return -att;
								}
							}
							return 0;
						}
						var es=ui.selected.targets[0].getCards('e');
						var i;
						var att2=get.sgn(get.attitude(player,ui.selected.targets[0]));
						for(i=0;i<es.length;i++){
							if(sgnatt!=0&&att2!=0&&sgnatt!=att2&&
								get.sgn(get.value(es[i],ui.selected.targets[0]))==-att2&&
								get.sgn(get.effect(target,es[i],player,target))==sgnatt&&
								target.canEquip(es[i])){
								return Math.abs(att);
							}
						}
						if(i==es.length&&(_status.event.nojudge||!ui.selected.targets[0].countCards('j',function(card){
							return target.canAddJudge(card);
						})||att2<=0)){
							return 0;
						}
						return -att*att2;
					});
					next.set('multitarget',true);
					next.set('targetprompt',_status.event.targetprompt||['被移走','移动目标']);
					next.set('prompt',event.prompt||'移动场上的一张牌');
					if(event.prompt2) next.set('prompt2',event.prompt2);
					if(event.forced) next.set('forced',true);
					'step 1'
					event.result=result;
					if(result.bool){
						player.line2(result.targets,'green');
						event.targets=result.targets;
					}
					else{
						event.finish();
					}
					'step 2'
					game.delay();
					'step 3'
					if(targets.length==2){
						player.choosePlayerCard('ej',true,function(button){
							var player=_status.event.player;
							var targets0=_status.event.targets0;
							var targets1=_status.event.targets1;
							if(get.attitude(player,targets0)>0&&get.attitude(player,targets1)<0){
								if(get.position(button.link)=='j') return 12;
								if(get.value(button.link,targets0)<0&&get.effect(targets1,button.link,player,targets1)>0) return 10;
								return 0;
							}
							else{
								if(get.position(button.link)=='j') return -10;
								return get.value(button.link)*get.effect(targets1,button.link,player,targets1);
							}
						},targets[0]).set('nojudge',event.nojudge||false).set('targets0',targets[0]).set('targets1',targets[1]).set('filterButton',function(button){
							var targets1=_status.event.targets1;
							if(get.position(button.link)=='j'){
								if(_status.event.nojudge) return false;
								return targets1.canAddJudge(button.link);
							}
							else{
								return targets1.canEquip(button.link);
							}
						});
					}
					else{
						event.finish();
					}
					'step 4'
					if(result.bool&&result.links.length){
						var link=result.links[0];
						if(get.position(link)=='e'){
							event.targets[1].equip(link);
						}
						else if(link.viewAs){
							event.targets[1].addJudge({name:link.viewAs},[link]);
						}
						else{
							event.targets[1].addJudge(link);
						}
						event.targets[0].$give(link,event.targets[1],false);
						game.log(event.targets[0],'的',link,'被移动给了',event.targets[1])
						event.result.card=link;
						event.result.position=get.position(link);
						game.delay();
					}
				},
				useCard:function(){
					"step 0"
					if(!card){
						console.log('err: no card',get.translation(event.player));
						event.finish();
						return;
					}
					if(!get.info(card,false).noForceDie) event.forceDie=true;
					if(cards.length){
						var owner=(get.owner(cards[0])||player);
						var next=owner.lose(cards,'visible',ui.ordering).set('type','use');
						var directDiscard=[];
						for(var i=0;i<cards.length;i++){
							if(!next.cards.contains(cards[i])){
								directDiscard.push(cards[i]);
							}
						}
						if(directDiscard.length) game.cardsGotoOrdering(directDiscard);
					}
					//player.using=cards;
					var cardaudio=true;
					if(event.skill){
						if(lib.skill[event.skill].audio){
							cardaudio=false;
						}
						if(lib.skill[event.skill].log!=false){
							player.logSkill(event.skill);
						}
						if(get.info(event.skill).popname){
							player.tryCardAnimate(card,event.card.name,'metal',true);
						}
					}
					else if(!event.nopopup){
						if(lib.translate[event.card.name+'_pop']){
							player.tryCardAnimate(card,lib.translate[event.card.name+'_pop'],'metal');
						}
						else{
							player.tryCardAnimate(card,event.card.name,'metal');
						}
					}	
					if(event.audio===false){
						cardaudio=false;
					}
					if(cardaudio) game.broadcastAll((player,card)=>{
						if(!lib.config.background_audio||get.type(card)=='equip'&&!lib.config.equip_audio) return;
						const sex=player.sex=='female'?'female':'male';
						var nature=get.natureList(card)[0];
						if(card.name=='sha'&&['fire','thunder','ice','stab'].includes(nature)){
							game.playAudio('card',sex,`${card.name}_${nature}`);
							return;
						}
						const audio=lib.card[card.name].audio;
						if(typeof audio=='string'){
							const audioInfo=audio.split(':');
							if(audio.startsWith('db:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${card.name}_${sex}.${audioInfo[3]||'mp3'}`);
							else if(audio.startsWith('ext:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${card.name}_${sex}.${audioInfo[2]||'mp3'}`);
							else game.playAudio('card',sex,`${audioInfo[0]}.${audioInfo[1]||'mp3'}`);
						}
						else game.playAudio('card',sex,card.name);
					},player,card);
					if(event.animate!=false&&event.line!=false){
						if(card.name=='wuxie'&&event.getParent()._info_map){
							var evtmap=event.getParent()._info_map;
							if(evtmap._source) evtmap=evtmap._source;
							var lining=(evtmap.multitarget?evtmap.targets:evtmap.target)||event.player;
							if(Array.isArray(lining)&&event.getTrigger().name=='jiedao'){
								player.line(lining[0],'green');
							}
							else{
								player.line(lining,'green');
							}
						}
						else if(card.name=='youdishenru'&&event.getParent().source){
							var lining=event.getParent().sourcex||event.getParent().source2||event.getParent().source;
							if(lining==player&&event.getParent().sourcex2){
								lining=event.getParent().sourcex2;
							}
							if(Array.isArray(lining)&&event.getTrigger().name=='jiedao'){
								player.line(lining[0],'green');
							}
							else{
								player.line(lining,'green');
							}
						}
						else{
							var config={};
							var nature=get.natureList(card)[0];
							if(nature||card.classList&&card.classList.contains(nature)) config.color=nature;
							if(event.addedTarget){
								player.line2(targets.concat(event.addedTargets),config);
							}
							else if(get.info(card,false).multitarget&&targets.length>1&&!get.info(card,false).multiline){
								player.line2(targets,config);
							}
							else{
								player.line(targets,config);
							}
						}
						if(event.throw!==false) player.$throw(cards);
						if(lib.config.sync_speed&&cards[0]&&cards[0].clone){
							var waitingForTransition=get.time();
							event.waitingForTransition=waitingForTransition;
							cards[0].clone.listenTransition(function(){
								if(_status.waitingForTransition==waitingForTransition&&_status.paused){
									game.resume();
								}
								delete event.waitingForTransition;
							});
						}
					}
					event.id=get.id();
					if(!Array.isArray(event.excluded)) event.excluded=[];
					if(!Array.isArray(event.directHit)) event.directHit=[];
					if(typeof event.customArgs!='object'||typeof event.customArgs.default!='object') event.customArgs={default:{}};
					if(typeof event.baseDamage!='number') event.baseDamage=get.info(card,false).baseDamage||1;
					if(typeof event.effectCount!='number') event.effectCount=get.info(card,false).effectCount||1;
					event.effectedCount=0;
					if(event.oncard){
						event.oncard(event.card,event.player);
					}
					player.actionHistory[player.actionHistory.length-1].useCard.push(event);
					game.getGlobalHistory().useCard.push(event);
					if(event.addCount!==false){
						if(player.stat[player.stat.length-1].card[card.name]==undefined){
							player.stat[player.stat.length-1].card[card.name]=1;
						}
						else{
							player.stat[player.stat.length-1].card[card.name]++;
						}
					}
					if(event.skill){
						if(player.stat[player.stat.length-1].skill[event.skill]==undefined){
							player.stat[player.stat.length-1].skill[event.skill]=1;
						}
						else{
							player.stat[player.stat.length-1].skill[event.skill]++;
						}
						var sourceSkill=get.info(event.skill).sourceSkill;
						if(sourceSkill){
							if(player.stat[player.stat.length-1].skill[sourceSkill]==undefined){
								player.stat[player.stat.length-1].skill[sourceSkill]=1;
							}
							else{
								player.stat[player.stat.length-1].skill[sourceSkill]++;
							}
						}
					}
					if(targets.length){
						var str=(targets.length==1&&targets[0]==player)?'#b自己':targets;
						if(cards.length&&!card.isCard){
							if(event.addedTarget){
								game.log(player,'对',str,'使用了',card,'(',cards,',指向',event.addedTargets,')');
							}
							else{
								game.log(player,'对',str,'使用了',card,'(',cards,')');
							}
						}
						else{
							if(event.addedTarget){
								game.log(player,'对',str,'使用了',card,'(指向',event.addedTargets,')');
							}
							else{
								game.log(player,'对',str,'使用了',card);
							}
						}
					}
					else{
						if(cards.length&&!card.isCard){
							if(event.addedTarget){
								game.log(player,'使用了',card,'(',cards,',指向',event.addedTargets,')');
							}
							else{
								game.log(player,'使用了',card,'(',cards,')');
							}
						}
						else{
							if(event.addedTarget){
								game.log(player,'使用了',card,'(指向',event.addedTargets,')');
							}
							else{
								game.log(player,'使用了',card);
							}
						}
					}
					if(card.name=='wuxie'){
						game.logv(player,[card,cards],[event.getTrigger().card]);
					}
					else{
						game.logv(player,[card,cards],targets);
					}
					event.trigger('useCard1');
					"step 1"
					event.trigger('yingbian');
					"step 2"
					event.trigger('useCard2');
					"step 3"
					event.trigger('useCard');
					event._oncancel=function(){
						game.broadcastAll(function(id){
							if(ui.tempnowuxie&&ui.tempnowuxie._origin==id){
								ui.tempnowuxie.close();
								delete ui.tempnowuxie;
							}
						},event.id);
					};
					"step 4"
					event.sortTarget=function(animate,sort){
						var info=get.info(card,false);
						if(num==0&&targets.length>1){
							if(!info.multitarget){
								if(!event.fixedSeat&&!sort){
									targets.sortBySeat((_status.currentPhase||player));
								}
								if(animate)	for(var i=0;i<targets.length;i++){
									targets[i].animate('target');
								}
							}
							else if(animate){
								for(var i=0;i<targets.length;i++){
									targets[i].animate('target');
								}
							}
						}
					}
					event.sortTarget();
					event.getTriggerTarget=function(list1,list2){
						var listx=list1.slice(0).sortBySeat((_status.currentPhase||player));
						for(var i=0;i<listx.length;i++){
							if(get.numOf(list2,listx[i])<get.numOf(listx,listx[i])) return listx[i];
						}
						return null;
					}
					"step 5"
					if(event.all_excluded) return;
					if(!event.triggeredTargets1) event.triggeredTargets1=[];
					var target=event.getTriggerTarget(targets,event.triggeredTargets1);
					if(target){
						event.triggeredTargets1.push(target);
						var next=game.createEvent('useCardToPlayer',false);
						if(!event.isFirstTarget1){
							event.isFirstTarget1=true;
							next.isFirstTarget=true;
						}
						next.setContent('emptyEvent');
						next.targets=targets;
						next.target=target;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.excluded=event.excluded;
						next.directHit=event.directHit;
						next.customArgs=event.customArgs;
						if(event.forceDie) next.forceDie=true;
						event.redo();
					}
					"step 6"
					if(event.all_excluded) return;
					if(!event.triggeredTargets2) event.triggeredTargets2=[];
					var target=event.getTriggerTarget(targets,event.triggeredTargets2);
					if(target){
						event.triggeredTargets2.push(target);
						var next=game.createEvent('useCardToTarget',false);
						if(!event.isFirstTarget2){
							event.isFirstTarget2=true;
							next.isFirstTarget=true;
						}
						next.setContent('emptyEvent');
						next.targets=targets;
						next.target=target;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.excluded=event.excluded;
						next.directHit=event.directHit;
						next.customArgs=event.customArgs;
						if(event.forceDie) next.forceDie=true;
						event.redo();
					}
					"step 7"
					var info=get.info(card,false);
					if(!info.nodelay&&event.animate!=false){
						if(event.delayx!==false){
							if(event.waitingForTransition){
								_status.waitingForTransition=event.waitingForTransition;
								game.pause();
							}
							else{
								game.delayx();
							}
						}
					}
					"step 8"
					if(event.all_excluded) return;
					if(!event.triggeredTargets3) event.triggeredTargets3=[];
					var target=event.getTriggerTarget(targets,event.triggeredTargets3);
					if(target){
						event.triggeredTargets3.push(target);
						var next=game.createEvent('useCardToPlayered',false);
						if(!event.isFirstTarget3){
							event.isFirstTarget3=true;
							next.isFirstTarget=true;
						}
						next.setContent('emptyEvent');
						next.targets=targets;
						next.target=target;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.excluded=event.excluded;
						next.directHit=event.directHit;
						next.customArgs=event.customArgs;
						if(event.forceDie) next.forceDie=true;
						event.redo();
					}
					"step 9"
					if(event.all_excluded) return;
					if(!event.triggeredTargets4) event.triggeredTargets4=[];
					var target=event.getTriggerTarget(targets,event.triggeredTargets4);
					if(target){
						event.triggeredTargets4.push(target);
						var next=game.createEvent('useCardToTargeted',false);
						if(!event.isFirstTarget4){
							event.isFirstTarget4=true;
							next.isFirstTarget=true;
						}
						next.setContent('emptyEvent');
						next.targets=targets;
						next.target=target;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.excluded=event.excluded;
						next.directHit=event.directHit;
						next.customArgs=event.customArgs;
						if(event.forceDie) next.forceDie=true;
						if(targets.length==event.triggeredTargets4.length){
							event.sortTarget();
						}
						event.redo();
					}
					"step 10"
					if(event.all_excluded) return;
					event.effectedCount++;
					event.num=0;
					var info=get.info(card,false);
					if(info.contentBefore){
						var next=game.createEvent(card.name+'ContentBefore');
						next.setContent(info.contentBefore);
						next.targets=targets;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.type='precard';
						if(event.forceDie) next.forceDie=true;
					}
					else if(info.reverseOrder&&get.is.versus()&&targets.length>1){
						var next=game.createEvent(card.name+'ContentBefore');
						next.setContent('reverseOrder');
						next.targets=targets;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.type='precard';
						if(event.forceDie) next.forceDie=true;
					}
					else if(info.singleCard&&info.filterAddedTarget&&event.addedTargets&&event.addedTargets.length<targets.length){
						var next=game.createEvent(card.name+'ContentBefore');
						next.setContent('addExtraTarget');
						next.target=target;
						next.targets=targets;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.type='precard';
						next.addedTarget=event.addedTarget;
						next.addedTargets=event.addedTargets;
						if(event.forceDie) next.forceDie=true;
					}
					"step 11"
					if(event.all_excluded) return;
					var info=get.info(card,false);
					if(num==0&&targets.length>1){
						event.sortTarget(true,true);
					}
					if(targets[num]&&targets[num].isDead()) return;
					if(targets[num]&&targets[num].isOut()) return;
					if(targets[num]&&targets[num].removed) return;
					if(targets[num]&&info.ignoreTarget&&info.ignoreTarget(card,player,targets[num])) return;
					if(targets.length==0&&!info.notarget) return;
					if(targets[num]&&event.excluded.contains(targets[num])){
					var next=game.createEvent('useCardToExcluded',false);
						next.setContent('emptyEvent');
						next.targets=targets;
						next.target=targets[num];
						next.num=num;
						next.card=card;
						next.cards=cards;
						next.player=player;
						return;
					};
					var next=game.createEvent(card.name);
					next.setContent(info.content);
					next.targets=targets;
					next.card=card;
					next.cards=cards;
					next.player=player;
					next.num=num;
					next.type='card';
					next.skill=event.skill;
					next.multitarget=info.multitarget;
					next.preResult=event.preResult;
					next.baseDamage=event.baseDamage;
					if(event.forceDie) next.forceDie=true;
					if(event.addedTargets){
						next.addedTargets=event.addedTargets;
						next.addedTarget=event.addedTargets[num];
						next._targets=event._targets;
					}
					if(info.targetDelay===false){
						event.targetDelay=false;
					}
					next.target=targets[num];
					for(var i in event.customArgs.default) next[i]=event.customArgs.default[i];
					if(next.target&&event.customArgs[next.target.playerid]){
						var customArgs=event.customArgs[next.target.playerid];
						for(var i in customArgs) next[i]=customArgs[i];
					}
					if(next.target&&event.directHit.contains(next.target)) next.directHit=true;
					if(next.target&&!info.multitarget){
						if(num==0&&targets.length>1){
							// var ttt=next.target;
							// setTimeout(function(){ttt.animate('target');},0.5*lib.config.duration);
						}
						else{
							next.target.animate('target');
						}
					}
					if(!info.nodelay&&num>0){
						if(event.targetDelay!==false){
							game.delayx(0.5);
						}
					}
					"step 12"
					if(event.all_excluded) return;
					if(!get.info(event.card,false).multitarget&&num<targets.length-1&&!event.cancelled){
						event.num++;
						event.goto(11);
					}
					"step 13"
					if(event.all_excluded) return;
					if(get.info(card,false).contentAfter){
						var next=game.createEvent(card.name+'ContentAfter');
						next.setContent(get.info(card,false).contentAfter);
						next.targets=targets;
						next.card=card;
						next.cards=cards;
						next.player=player;
						next.skill=event.skill;
						next.preResult=event.preResult;
						next.type='postcard';
						if(event.forceDie) next.forceDie=true;
					}
					"step 14"
					if(event.all_excluded) return;
					if(event.effectedCount<event.effectCount){
						if(document.getElementsByClassName('thrown').length){
							if(event.delayx!==false&&get.info(event.card,false).finalDelay!==false) game.delayx();
						}
						event.goto(10);
					}
					"step 15"
					if(event.postAi){
						event.player.logAi(event.targets,event.card);
					}
					if(event._result){
						event.result=event._result;
					}
					//delete player.using;
					if(document.getElementsByClassName('thrown').length){
						if(event.delayx!==false&&get.info(event.card,false).finalDelay!==false) game.delayx();
					}
					else{
						event.finish();
					}
					"step 16"
					event._oncancel();
				},
				useSkill:function(){
					"step 0"
					var info=get.info(event.skill);
					if(!info.noForceDie) event.forceDie=true;
					if(!info.noForceOut) event.includeOut=true;
					event._skill=event.skill;
					game.trySkillAudio(event.skill,player);
					var checkShow=player.checkShow(event.skill);
					if(info.discard!=false&&info.lose!=false&&!info.viewAs){
						player.discard(cards).delay=false;
						if(lib.config.low_performance){
							event.discardTransition=true;
						}
					}
					else{
						if(info.lose!=false){
							if(info.losetrigger==false){
								var losecard=player.lose(cards,ui.special)._triggered=null;
							}
							else{
								var losecard=player.lose(cards,ui.special);
								if(info.visible) losecard.visible=true;
								if(info.loseTo) losecard.position=ui[info.loseTo];
								if(info.insert) losecard.insert_card=true;
								if(losecard.position==ui.special&&info.toStorage) losecard.toStorage=true;
							}
						}
						if(!info.prepare&&info.viewAs){
							player.$throw(cards);
							if(losecard) losecard.visible=true;
							if(lib.config.sync_speed&&cards[0]&&cards[0].clone){
								var waitingForTransition=get.time();
								event.waitingForTransition=waitingForTransition;
								cards[0].clone.listenTransition(function(){
									if(_status.waitingForTransition==waitingForTransition&&_status.paused){
										game.resume();
									}
									delete event.waitingForTransition;
								});
							}
						}
					}
					if(info.line!=false&&targets.length){
						var config={};
						if(get.is.object(info.line)) config=info.line;
						else if(info.line=='fire'){
							config.color='fire';
						}
						else if(info.line=='thunder'){
							config.color='thunder';
						}
						else if(info.line===undefined||info.line=='green'){
							config.color='green';
						}
						if(info.multitarget&&!info.multiline&&targets.length>1){
							player.line2(targets,config);
						}
						else{
							player.line(targets,config);
						}
					}
					var str='';
					if(targets&&targets.length&&info.log!='notarget'){
						str+='对<span class="bluetext">'+(targets[0]==player?'自己':get.translation(targets[0]));
						for(var i=1;i<targets.length;i++){
							str+='、'+(targets[i]==player?'自己':get.translation(targets[i]));
						}
						str+='</span>'
					}
					str+='发动了';
					if(!info.direct&&info.log!==false){
						game.log(player,str,'【'+get.skillTranslation(skill,player)+'】');
						if(info.logv!==false) game.logv(player,skill,targets);
						player.trySkillAnimate(skill,skill,checkShow);
					}
					if(event.addCount!=false){
						if(player.stat[player.stat.length-1].skill[skill]==undefined){
							player.stat[player.stat.length-1].skill[skill]=1;
						}
						else{
							player.stat[player.stat.length-1].skill[skill]++;
						}
						var sourceSkill=get.info(skill).sourceSkill;
						if(sourceSkill){
							if(player.stat[player.stat.length-1].skill[sourceSkill]==undefined){
								player.stat[player.stat.length-1].skill[sourceSkill]=1;
							}
							else{
								player.stat[player.stat.length-1].skill[sourceSkill]++;
							}
						}
					}
					if(player.stat[player.stat.length-1].allSkills==undefined){
						player.stat[player.stat.length-1].allSkills=1;
					}
					else{
						player.stat[player.stat.length-1].allSkills++;
					}
					if(info.prepare){
						switch(info.prepare){
							case 'give':if(losecard) losecard.visible=true;player.$give(cards,targets[0]);break;
							case 'give2':player.$give(cards.length,targets[0]);break;
							case 'throw':if(losecard) losecard.visible=true;player.$throw(cards);break;
							case 'throw2':player.$throw(cards.length);break;
							default:info.prepare(cards,player,targets);
						}
					}
					if(info.round){
						var roundname=skill+'_roundcount';
						player.storage[roundname]=game.roundNumber;
						player.syncStorage(roundname);
						player.markSkill(roundname);
					}
					var name=event.skill;
					var players=player.getSkills(false,false,false);
					var equips=player.getSkills('e');
					var global=lib.skill.global.slice(0);
					var logInfo={
						skill:name,
						targets:targets,
						event:_status.event,
					};
					if(info.sourceSkill){
						logInfo.sourceSkill=info.sourceSkill;
						if(global.contains(info.sourceSkill)){
							logInfo.type='global';
						}
						else if(players.contains(info.sourceSkill)){
							logInfo.type='player';
						}
						else if(equips.contains(info.sourceSkill)){
							logInfo.type='equip';
						}
					}
					else{
						if(global.contains(name)){
							logInfo.sourceSkill=name;
							logInfo.type='global';
						}
						else if(players.contains(name)){
							logInfo.sourceSkill=name;
							logInfo.type='player';
						}
						else if(equips.contains(name)){
							logInfo.sourceSkill=name;
							logInfo.type='equip';
						}
						else{
							var bool=false;
							for(var i of players){
								var expand=[i];
								game.expandSkills(expand);
								if(expand.contains(name)){
									bool=true;
									logInfo.sourceSkill=i;
									logInfo.type='player';
									break;
								}
							}
							if(!bool){
								for(var i of players){
									var expand=[i];
									game.expandSkills(expand);
									if(expand.contains(name)){
										logInfo.sourceSkill=i;
										logInfo.type='equip';
										break;
									}
								}
							}
						}
					}
					event.sourceSkill=logInfo.sourceSkill;
					event.type=logInfo.type;
					player.getHistory('useSkill').push(logInfo);
					event.trigger('useSkill');
					"step 1"
					var info=get.info(event.skill);
					if(info&&info.contentBefore){
						var next=game.createEvent(event.skill+'ContentBefore');
						next.setContent(info.contentBefore);
						next.targets=targets;
						next.cards=cards;
						next.player=player;
						if(event.forceDie) next.forceDie=true;
						if(event.includeOut) next.includeOut=true;
					}
					"step 2"
					if(!event.skill){
						console.log('error: no skill',get.translation(event.player),event.player.getSkills());
						if(event._skill){
							event.skill=event._skill;
							console.log(event._skill);
						}
						else{
							event.finish();
							return;
						}
					}
					var info=get.info(event.skill);
					if(targets[num]&&targets[num].isDead()||
						targets[num]&&targets[num].isOut()||
						targets[num]&&targets[num].removed){
						if(!info.multitarget&&num<targets.length-1){
							event.num++;
							event.redo();
						}
						return;
					}
					var next=game.createEvent(event.skill);
					next.setContent(info.content);
					next.targets=targets;
					next.cards=cards;
					next.player=player;
					next.num=num;
					next.multitarget=info.multitarget;
					if(num==0&&next.targets.length>1){
						if(!info.multitarget){
							lib.tempSortSeat=player;
							targets.sort(lib.sort.seat);
							delete lib.tempSortSeat;
						}
						for(var i=0;i<targets.length;i++){
							targets[i].animate('target');
						}
					}
					next.target=targets[num];
					if(event.forceDie) next.forceDie=true;
					if(event.includeOut) next.includeOut=true;
					if(next.target&&!info.multitarget){
						if(num==0&&targets.length>1){
							// var ttt=next.target;
							// setTimeout(function(){ttt.animate('target');},0.5*lib.config.duration);
						}
						else{
							next.target.animate('target');
						}
					}
					if(num==0){
						if(typeof info.delay=='number') game.delay(info.delay);
						else if(info.delay!==false&&info.delay!==0){
							if(event.waitingForTransition){
								_status.waitingForTransition=event.waitingForTransition;
								game.pause();
							}
							else{
								game.delayx()
							}
						}
					}
					else game.delayx(0.5);
					if(!info.multitarget&&num<targets.length-1){
						event.num++;
						event.redo();
					}
					"step 3"
					var info=get.info(event.skill);
					if(info&&info.contentAfter){
						var next=game.createEvent(event.skill+'ContentAfter');
						next.setContent(info.contentAfter);
						next.targets=targets;
						next.cards=cards;
						next.player=player;
						if(event.forceDie) next.forceDie=true;
						if(event.includeOut) next.includeOut=true;
					}
					"step 4"
					if(player.getStat().allSkills>200){
						player._noSkill=true;
						console.log(player.name,event.skill);
					}
					if(document.getElementsByClassName('thrown').length){
						if(event.skill&&get.info(event.skill).delay!==false&&get.info(event.skill).delay!==0) game.delayx();
					}
					else{
						event.finish();
					}
					"step 5"
					ui.clear();
				},
				draw:function(){
					// if(lib.config.background_audio){
					// 	game.playAudio('effect','draw');
					// }
					// game.broadcast(function(){
					//     if(lib.config.background_audio){
					// 		game.playAudio('effect','draw');
					// 	}
					// });
					if(typeof event.minnum=='number'&&num<event.minnum){
						num=event.minnum;
					}
					if(event.drawDeck){
						if(event.drawDeck>num){
							event.drawDeck=num;
						}
						num-=event.drawDeck;
					}
					if(event.log!=false){
						if(num>0){
							if(event.bottom) game.log(player,'从牌堆底摸了'+get.cnNumber(num)+'张牌');
							else game.log(player,'摸了'+get.cnNumber(num)+'张牌');
						}
						if(event.drawDeck){
							game.log(player,'从牌库中获得了'+get.cnNumber(event.drawDeck)+'张牌');
						}
					}
					var cards;
					if(num>0){
						if(event.bottom) cards=get.bottomCards(num);
						else if(player.getTopCards) cards=player.getTopCards(num);
						else cards=get.cards(num);
					}
					else{
						cards=[];
					}
					if(event.drawDeck){
						cards=cards.concat(player.getDeckCards(event.drawDeck));
					}
					if(event.animate!=false){
						if(event.visible){
							var next=player.gain(cards,'gain2');
							if(event.bottom) game.log(player,'从牌堆底摸了'+get.cnNumber(num)+'张牌(',cards,')');
							else game.log(player,'摸了'+get.cnNumber(num)+'张牌(',cards,')');
						}
						else{
							var next=player.gain(cards,'draw');
						}
					}
					else{
						var next=player.gain(cards);
						if(event.$draw){
							player.$draw(cards.length);
						}
					}
					if(event.gaintag) next.gaintag.addArray(event.gaintag);
					event.result=cards;
				},
				discard:function(){
					"step 0"
					game.log(player,'弃置了',cards);
					event.done=player.lose(cards,event.position,'visible');
					event.done.type='discard';
					if(event.discarder) event.done.discarder=event.discarder;
					"step 1"
					event.trigger('discard');
				},
				loseToDiscardpile:function(){
					"step 0"
					if(event.log!=false) game.log(player,'将',cards,'置入了弃牌堆');
					var next=player.lose(cards,event.position);
					if(event.insert_index) next.insert_index=event.insert_index;
					if(event.insert_card) next.insert_card=true;
					if(!event.blank) next.visible=true;
					next.type='loseToDiscardpile';
					event.done=next;
					"step 1"
					event.trigger('loseToDiscardpile');
				},
				respond:function(){
					'step 0'
					var cardaudio=true;
					if(event.skill){
						if(lib.skill[event.skill].audio){
							cardaudio=false;
						}
						player.logSkill(event.skill);
						player.checkShow(event.skill,true);
						if(lib.skill[event.skill].onrespond&&!game.online){
							lib.skill[event.skill].onrespond(event,player);
						}
					}
					else if(!event.nopopup) player.tryCardAnimate(card,card.name,'wood');
					if(cardaudio&&event.getParent(3).name=='useCard') game.broadcastAll((player,card)=>{
						if(!lib.config.background_audio) return;
						const sex=player.sex=='female'?'female':'male',audio=lib.card[card.name].audio;
						if(typeof audio=='string'){
							const audioInfo=audio.split(':');
							if(audio.startsWith('db:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${card.name}_${sex}.${audioInfo[3]||'mp3'}`);
							else if(audio.startsWith('ext:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${card.name}_${sex}.${audioInfo[2]||'mp3'}`);
							else game.playAudio('card',sex,`${audioInfo[0]}.${audioInfo[1]||'mp3'}`);
						}
						else game.playAudio('card',sex,card.name);
					},player,card);
					if(event.skill){
						if(player.stat[player.stat.length-1].skill[event.skill]==undefined){
							player.stat[player.stat.length-1].skill[event.skill]=1;
						}
						else{
							player.stat[player.stat.length-1].skill[event.skill]++;
						}
						var sourceSkill=get.info(event.skill).sourceSkill;
						if(sourceSkill){
							if(player.stat[player.stat.length-1].skill[sourceSkill]==undefined){
								player.stat[player.stat.length-1].skill[sourceSkill]=1;
							}
							else{
								player.stat[player.stat.length-1].skill[sourceSkill]++;
							}
						}
					}
					if(cards.length&&(cards.length>1||cards[0].name!=card.name)){
						game.log(player,'打出了',card,'(',cards,')');
					}
					else{
						game.log(player,'打出了',card);
					}
					player.actionHistory[player.actionHistory.length-1].respond.push(event);
					if(cards.length){
						var owner=(get.owner(cards[0])||player);
						var next=owner.lose(cards,'visible',ui.ordering).set('type','use');
						var directDiscard=[];
						for(var i=0;i<cards.length;i++){
							if(!next.cards.contains(cards[i])){
								directDiscard.push(cards[i]);
							}
						}
						if(directDiscard.length) game.cardsGotoOrdering(directDiscard);
					}
					if(event.animate!=false&&event.throw!==false){
						for(var i=0;i<cards.length;i++){
							player.$throw(cards[i]);
							if(event.highlight){
								cards[i].clone.classList.add('thrownhighlight');
								game.addVideo('highlightnode',player,get.cardInfo(cards[i]));
							}
						}
						if(event.highlight){
							game.broadcast(function(cards){
								for(var i=0;i<cards.length;i++){
									if(cards[i].clone){
										cards[i].clone.classList.add('thrownhighlight');
									}
								}
							},cards);
						}
					}
					event.trigger('respond');
					'step 1'
					game.delayx(0.5);
				},
				swapHandcards:function(){
					'step 0'
					event.cards1=event.cards1||player.getCards('h');
					event.cards2=event.cards2||target.getCards('h');
					game.loseAsync({
						player:player,
						target:target,
						cards1:event.cards1,
						cards2:event.cards2,
					}).setContent('swapHandcardsx');
					'step 1'
					game.loseAsync({
						gain_list:[
							[player,event.cards2.filterInD()],
							[target,event.cards1.filterInD()]
						],
					}).setContent('gaincardMultiple');
					'step 2'
					game.delayx();
				},
				swapHandcardsx:function(){
					'step 0'
					player.$giveAuto(event.cards1,target);
					target.$giveAuto(event.cards2,player);
					'step 1'
					event.cards=event.cards1;
					var next=player.lose(event.cards,ui.ordering);
					next.getlx=false;
					next.relatedEvent=event.getParent();
					if(player==game.me){
						event.delayed=true;
					}
					else{
						next.delay=false;
					}
					'step 2'
					event.cards=event.cards2;
					var next=target.lose(event.cards,ui.ordering);
					next.getlx=false;
					next.relatedEvent=event.getParent();
					if(target==game.me){
						event.delayed=true;
					}
					else{
						next.delay=false;
					}
					'step 3'
					if(!event.delayed) game.delay();
				},
				gainMultiple:function(){
					'step 0'
					event.delayed=false;
					event.num=0;
					event.cards=[];
					'step 1'
					player.gainPlayerCard(targets[num],event.position,true).set('boolline',false).set('delay',num==targets.length-1);
					'step 2'
					if(result.bool){
						event.cards.addArray(result.cards);
						if(num==targets.length-1) event.delayed=true;
					}
					event.num++;
					if(event.num<targets.length){
						event.goto(1);
					}
					'step 3'
					if(!event.delayed) game.delay();
				},
				gain:function(){
					"step 0"
					if(event.animate=='give') event.visible=true;
					if(cards){
						var map={};
						for(var i of cards){
							var owner=get.owner(i,'judge');
							if(owner&&(owner!=player||get.position(i)!='h')){
								var id=owner.playerid;
								if(!map[id]) map[id]=[[],[],[]];
								map[id][0].push(i);
								var position=get.position(i);
								if(position=='h') map[id][1].push(i);
								else map[id][2].push(i);
							}
							else if(!event.updatePile&&get.position(i)=='c') event.updatePile=true;
						}
						event.losing_map=map;
						for(var i in map){
							var owner=(_status.connectMode?lib.playerOL:game.playerMap)[i];
							var next=owner.lose(map[i][0],ui.special).set('type','gain').set('forceDie',true).set('getlx',false);
							if(event.visible==true) next.visible=true;
							event.relatedLose=next;
						}
					}
					else{
						event.finish();
					}
					"step 1"
					for(var i=0;i<cards.length;i++){
						if(cards[i].destroyed){
							if(player.hasSkill(cards[i].destroyed)){
								delete cards[i].destroyed;
							}
							else{
								cards.splice(i--,1);
							}
						}
						else if(event.losing_map){
							for(var id in event.losing_map){
								if(event.losing_map[id][0].contains(cards[i])){
									var source=(_status.connectMode?lib.playerOL:game.playerMap)[id];
									var hs=source.getCards('hejsx');
									if(hs.contains(cards[i])){
										cards.splice(i--,1);
									}
								}
							}
						}
					}
					if(cards.length==0){
						event.finish();
						return;
					}
					player.getHistory('gain').push(event);
					//if(event.source&&event.delay!==false) game.delayx();
					"step 2"
					if(player.getStat().gain==undefined){
						player.getStat().gain=cards.length;
					}
					else{
						player.getStat().gain+=cards.length;
					}
					"step 3"
					var sort;
					var frag1=document.createDocumentFragment();
					var frag2=document.createDocumentFragment();
					var hs=player.getCards('hs');
					for(var i=0;i<cards.length;i++){
						if(hs.contains(cards[i])){
							cards.splice(i--,1);
						}
					}
					for(var num=0;num<cards.length;num++){
						sort=lib.config.sort_card(cards[num]);
						if(lib.config.reverse_sort) sort=-sort;
						cards[num].fix();
						cards[num].style.transform='';
						cards[num].addGaintag(event.gaintag);
						if(_status.discarded){
							_status.discarded.remove(cards[num]);
						}
						// cards[num].vanishtag.length=0;
						for(var num2=0;num2<cards[num].vanishtag.length;num2++){
							if(cards[num].vanishtag[num2][0]!='_'){
								cards[num].vanishtag.splice(num2--,1);
							}
						}
						if(player==game.me){
							cards[num].classList.add('drawinghidden');
						}
						if(get.is.singleHandcard()||sort>1) frag1.appendChild(cards[num]);
						else frag2.appendChild(cards[num]);
					}
					var addv=function(){
						if(player==game.me){
							game.addVideo('gain12',player,[get.cardsInfo(frag1.childNodes),get.cardsInfo(frag2.childNodes),event.gaintag]);
						}
					};
					var broadcast=function(){
						game.broadcast(function(player,cards,num,gaintag){
							player.directgain(cards,null,gaintag);
							_status.cardPileNum=num;
						},player,cards,ui.cardPile.childNodes.length,event.gaintag);
					};
					if(event.animate=='draw'){
						player.$draw(cards.length);
						game.pause();
						setTimeout(function(){
							addv();
							player.node.handcards1.insertBefore(frag1,player.node.handcards1.firstChild);
							player.node.handcards2.insertBefore(frag2,player.node.handcards2.firstChild);
							player.update();
							if(player==game.me) ui.updatehl();
							broadcast();
							game.resume();
						},get.delayx(500,500));
					}
					else if(event.animate=='gain'){
						player.$gain(cards,event.log);
						game.pause();
						setTimeout(function(){
							addv();
							player.node.handcards1.insertBefore(frag1,player.node.handcards1.firstChild);
							player.node.handcards2.insertBefore(frag2,player.node.handcards2.firstChild);
							player.update();
							if(player==game.me) ui.updatehl();
							broadcast();
							game.resume();
						},get.delayx(700,700));
					}
					else if(event.animate=='gain2'||event.animate=='draw2'){
						var gain2t=300;
						if(player.$gain2(cards,event.log)&&player==game.me){
							gain2t=500;
						}
						game.pause();
						setTimeout(function(){
							addv();
							player.node.handcards1.insertBefore(frag1,player.node.handcards1.firstChild);
							player.node.handcards2.insertBefore(frag2,player.node.handcards2.firstChild);
							player.update();
							if(player==game.me) ui.updatehl();
							broadcast();
							game.resume();
						},get.delayx(gain2t,gain2t));
					}
					else if(event.animate=='give'||event.animate=='giveAuto'){
						var evtmap=event.losing_map;
						if(event.animate=='give'){
							for(var i in evtmap){
								var source=(_status.connectMode?lib.playerOL:game.playerMap)[i];
								source.$give(evtmap[i][0],player,event.log)
							}
						}
						else{
							for(var i in evtmap){
								var source=(_status.connectMode?lib.playerOL:game.playerMap)[i];
								if(evtmap[i][1].length) source.$giveAuto(evtmap[i][1],player,event.log);
								if(evtmap[i][2].length) source.$give(evtmap[i][2],player,event.log);
							}
						}
						game.pause();
						setTimeout(function(){
							addv();
							player.node.handcards1.insertBefore(frag1,player.node.handcards1.firstChild);
							player.node.handcards2.insertBefore(frag2,player.node.handcards2.firstChild);
							player.update();
							if(player==game.me) ui.updatehl();
							broadcast();
							game.resume();
						},get.delayx(500,500));
					}
					else if(typeof event.animate=='function'){
						var time=event.animate(event);
						game.pause();
						setTimeout(function(){
							addv();
							player.node.handcards1.insertBefore(frag1,player.node.handcards1.firstChild);
							player.node.handcards2.insertBefore(frag2,player.node.handcards2.firstChild);
							player.update();
							if(player==game.me) ui.updatehl();
							broadcast();
							game.resume();
						},get.delayx(time,time));
					}
					else{
						addv();
						player.node.handcards1.insertBefore(frag1,player.node.handcards1.firstChild);
						player.node.handcards2.insertBefore(frag2,player.node.handcards2.firstChild);
						player.update();
						if(player==game.me) ui.updatehl();
						broadcast();
						event.finish();
					}
					"step 4"
					game.delayx();
					if(event.updatePile) game.updateRoundNumber();
				},
				addToExpansion:function(){
					"step 0"
					if(event.animate=='give') event.visible=true;
					if(cards){
						var map={};
						for(var i of cards){
							var owner=get.owner(i,'judge');
							if(owner&&(owner!=player||get.position(i)!='x')){
								var id=owner.playerid;
								if(!map[id]) map[id]=[[],[],[]];
								map[id][0].push(i);
								var position=get.position(i);
								if(position=='h') map[id][1].push(i);
								else map[id][2].push(i);
							}
							else if(!event.updatePile&&get.position(i)=='c') event.updatePile=true;
						}
						event.losing_map=map;
						for(var i in map){
							var owner=(_status.connectMode?lib.playerOL:game.playerMap)[i];
							var next=owner.lose(map[i][0],ui.special).set('type','loseToExpansion').set('forceDie',true).set('getlx',false);
							if(event.visible==true) next.visible=true;
							event.relatedLose=next;
						}
					}
					else{
						event.finish();
					}
					"step 1"
					for(var i=0;i<cards.length;i++){
						if(cards[i].destroyed){
							if(player.hasSkill(cards[i].destroyed)){
								delete cards[i].destroyed;
							}
							else{
								cards.splice(i--,1);
							}
						}
						else if(event.losing_map){
							for(var id in event.losing_map){
								if(event.losing_map[id][0].contains(cards[i])){
									var source=(_status.connectMode?lib.playerOL:game.playerMap)[id];
									var hs=source.getCards('hejsx');
									if(hs.contains(cards[i])){
										cards.splice(i--,1);
									}
								}
							}
						}
					}
					if(cards.length==0){
						event.finish();
						return;
					}
					"step 2"
					var hs=player.getCards('x');
					for(var i=0;i<cards.length;i++){
						if(hs.contains(cards[i])){
							cards.splice(i--,1);
						}
					}
					for(var num=0;num<cards.length;num++){
						if(_status.discarded){
							_status.discarded.remove(cards[num]);
						}
						for(var num2=0;num2<cards[num].vanishtag.length;num2++){
							if(cards[num].vanishtag[num2][0]!='_'){
								cards[num].vanishtag.splice(num2--,1);
							}
						}
					}
					if(event.animate=='draw'){
						player.$draw(cards.length);
						if(event.log) game.log(player,'将',get.cnNumber(cards.length),'张牌置于了武将牌上');
						game.pause();
						setTimeout(function(){
							player.$addToExpansion(cards,null,event.gaintag);
							for(var i of event.gaintag) player.markSkill(i);
							game.resume();
						},get.delayx(500,500));
					}
					else if(event.animate=='gain'){
						player.$gain(cards,false);
						game.pause();
						setTimeout(function(){
							player.$addToExpansion(cards,null,event.gaintag);
							for(var i of event.gaintag) player.markSkill(i);
							game.resume();
						},get.delayx(700,700));
					}
					else if(event.animate=='gain2'||event.animate=='draw2'){
						var gain2t=300;
						if(player.$gain2(cards)&&player==game.me){
							gain2t=500;
						}
						game.pause();
						setTimeout(function(){
							player.$addToExpansion(cards,null,event.gaintag);
							for(var i of event.gaintag) player.markSkill(i);
							game.resume();
						},get.delayx(gain2t,gain2t));
					}
					else if(event.animate=='give'||event.animate=='giveAuto'){
						var evtmap=event.losing_map;
						if(event.animate=='give'){
							for(var i in evtmap){
								var source=(_status.connectMode?lib.playerOL:game.playerMap)[i];
								source.$give(evtmap[i][0],player,false);
								if(event.log) game.log(player,'将',evtmap[i][0],'置于了武将牌上');
							}
						}
						else{
							for(var i in evtmap){
								var source=(_status.connectMode?lib.playerOL:game.playerMap)[i];
								if(evtmap[i][1].length){
									source.$giveAuto(evtmap[i][1],player,false);
									if(event.log) game.log(player,'将',get.cnNumber(evtmap[i][1].length),'张牌置于了武将牌上');
								}
								if(evtmap[i][2].length){
									source.$give(evtmap[i][2],player,false);
									if(event.log) game.log(player,'将',evtmap[i][2],'置于了武将牌上');
								}
							}
						}
						game.pause();
						setTimeout(function(){
							player.$addToExpansion(cards,null,event.gaintag);
							for(var i of event.gaintag) player.markSkill(i);
							game.resume();
						},get.delayx(500,500));
					}
					else if(typeof event.animate=='function'){
						var time=event.animate(event);
						game.pause();
						setTimeout(function(){
							player.$addToExpansion(cards,null,event.gaintag);
							for(var i of event.gaintag) player.markSkill(i);
							game.resume();
						},get.delayx(time,time));
					}
					else{
						player.$addToExpansion(cards,null,event.gaintag);
						for(var i of event.gaintag) player.markSkill(i);
						event.finish();
					}
					"step 4"
					game.delayx();
					if(event.updatePile) game.updateRoundNumber();
				},
				lose:function(){
					"step 0"
					var evt=event.getParent();
					if((evt.name!='discard'||event.type!='discard')&&(evt.name!='loseToDiscardpile'||event.type!='loseToDiscardpile')){
						event.delay=false;
						return;
					}
					if(evt.delay===false) event.delay=false;
					if(evt.animate!=false){
						evt.discardid=lib.status.videoId++;
						game.broadcastAll(function(player,cards,id,visible){
							player.$throw(cards,null,'nobroadcast');
							var cardnodes=[];
							cardnodes._discardtime=get.time();
							for(var i=0;i<cards.length;i++){
								if(cards[i].clone){
									cardnodes.push(cards[i].clone);
									if(!visible){
										cards[i].clone.classList.add('infohidden');
										cards[i].clone.classList.add('infoflip');
									}
								}
							}
							ui.todiscard[id]=cardnodes;
						},player,cards,evt.discardid,event.visible);
						if(lib.config.sync_speed&&cards[0]&&cards[0].clone){
							if(evt.delay!=false){
								var waitingForTransition=get.time();
								evt.waitingForTransition=waitingForTransition;
								cards[0].clone.listenTransition(function(){
									if(_status.waitingForTransition==waitingForTransition&&_status.paused){
										game.resume();
									}
									delete evt.waitingForTransition;
								});
							}
							else if(evt.getParent().discardTransition){
								delete evt.getParent().discardTransition;
								var waitingForTransition=get.time();
								evt.getParent().waitingForTransition=waitingForTransition;
								cards[0].clone.listenTransition(function(){
									if(_status.waitingForTransition==waitingForTransition&&_status.paused){
										game.resume();
									}
									delete evt.getParent().waitingForTransition;
								});
							}
						}
					}
					"step 1"
					event.gaintag_map={};
					var hs=[],es=[],js=[],ss=[],xs=[];
					var unmarks=[];
					if(event.insert_card&&event.position==ui.cardPile) event.cards.reverse();
					var hej=player.getCards('hejsx');
					event.stockcards=cards.slice(0);
					for(var i=0;i<cards.length;i++){
						if(!hej.contains(cards[i])){
							cards.splice(i--,1);
							continue;
						}
						else if(cards[i].parentNode){
							if(cards[i].parentNode.classList.contains('equips')){
								cards[i].original='e';
								es.push(cards[i]);
							}
							else if(cards[i].parentNode.classList.contains('judges')){
								cards[i].original='j';
								js.push(cards[i]);
							}
							else if(cards[i].parentNode.classList.contains('expansions')){
								cards[i].original='x';
								xs.push(cards[i]);
								if(cards[i].gaintag&&cards[i].gaintag.length) unmarks.addArray(cards[i].gaintag);
							}
							else if(cards[i].parentNode.classList.contains('handcards')){
								if(cards[i].classList.contains('glows')){
									cards[i].original='s';
									ss.push(cards[i]);
								}
								else{
									cards[i].original='h';
									hs.push(cards[i]);
								}
							}
							else{
								cards[i].original=null;
							}
						}
						if(cards[i].gaintag&&cards[i].gaintag.length){
							event.gaintag_map[cards[i].cardid]=cards[i].gaintag.slice(0);
							cards[i].removeGaintag(true);
						}
						
						cards[i].style.transform+=' scale(0.2)';
						cards[i].classList.remove('glow');
						cards[i].classList.remove('glows');
						cards[i].recheck();
						
						var info=lib.card[cards[i].name];
						if(info.destroy||cards[i]._destroy){
							cards[i].delete();
							cards[i].destroyed=info.destroy||cards[i]._destroy;
						}
						else if(event.position){
							if(_status.discarded){
								if(event.position==ui.discardPile){
									_status.discarded.add(cards[i]);
								}
								else{
									_status.discarded.remove(cards[i]);
								}
							}
							if(event.insert_index){
								cards[i].fix();
								event.position.insertBefore(cards[i],event.insert_index(event,cards[i]));
							}
							else if(event.insert_card){
								cards[i].fix();
								event.position.insertBefore(cards[i],event.position.firstChild);
							}
							else if(event.position==ui.cardPile){
								cards[i].fix();
								event.position.appendChild(cards[i]);
							}
							else cards[i].goto(event.position);
						}
						else{
							cards[i].remove();
						}
						//if(ss.contains(cards[i])) cards.splice(i--,1);
					}
					if(player==game.me) ui.updatehl();
					ui.updatej(player);
					game.broadcast(function(player,cards,num){
						for(var i=0;i<cards.length;i++){
							cards[i].classList.remove('glow');
							cards[i].classList.remove('glows');
							cards[i].fix();
							cards[i].remove();
						}
						if(player==game.me){
							ui.updatehl();
						}
						ui.updatej(player);
						_status.cardPileNum=num;
					},player,cards,ui.cardPile.childNodes.length);
					game.addVideo('lose',player,[get.cardsInfo(hs),get.cardsInfo(es),get.cardsInfo(js),get.cardsInfo(ss)]);
					event.cards2=hs.concat(es);
					player.getHistory('lose').push(event);
					game.getGlobalHistory().cardMove.push(event);
					player.update();
					game.addVideo('loseAfter',player);
					event.num=0;
					if(event.position==ui.ordering){
						var evt=event.relatedEvent||event.getParent();
						if(!evt.orderingCards)	evt.orderingCards=[];
						if(!evt.noOrdering&&!evt.cardsOrdered){
							evt.cardsOrdered=true;
							var next=game.createEvent('orderingDiscard',false,evt.getParent());
							next.relatedEvent=evt;
							next.setContent('orderingDiscard');
						}
						if(!evt.noOrdering){
							evt.orderingCards.addArray(cards);
						}
					}
					else if(event.position==ui.cardPile){
						game.updateRoundNumber();
					}
					if(unmarks.length){
						for(var i of unmarks){
							player[(lib.skill[i]&&lib.skill[i].mark||player.hasCard((card)=>card.hasGaintag(i),'x'))?'markSkill':'unmarkSkill'](i);
						}
					}
					event.hs=hs;
					event.es=es;
					event.js=js;
					event.ss=ss;
					event.xs=xs;
					"step 2"
					if(num<cards.length){
						if(event.es.contains(cards[num])){
							event.loseEquip=true;
							player.removeEquipTrigger(cards[num]);
							var info=get.info(cards[num]);
							if(info.onLose&&(!info.filterLose||info.filterLose(cards[num],player))){
								event.goto(3);
								return;
							}
						}
						event.num++;
						event.redo();
					}
					else{
						if(event.loseEquip){
							player.addEquipTrigger();
						}
						event.goto(4);
					}
					"step 3"
					var info=get.info(cards[num]);
					if(info.loseDelay!=false&&(player.isAlive()||info.forceDie)){
						player.popup(cards[num].name);
						game.delayx();
					}
					if(Array.isArray(info.onLose)){
						for(var i=0;i<info.onLose.length;i++){
							var next=game.createEvent('lose_'+cards[num].name);
							next.setContent(info.onLose[i]);
							if(info.forceDie) next.forceDie=true;
							next.player=player;
							next.card=cards[num];
						}
					}
					else{
						var next=game.createEvent('lose_'+cards[num].name);
						next.setContent(info.onLose);
						next.player=player;
						if(info.forceDie) next.forceDie=true;
						next.card=cards[num];
					}
					event.num++;
					event.goto(2);
					"step 4"
					if(event.toRenku){
						_status.renku.addArray(cards.filter(function(card){
							return !card.destroyed;
						}));
						if(_status.renku.length>6){
							var cards=_status.renku.splice(0,_status.renku.length-6);
							game.log(cards,'从仁库进入了弃牌堆');
							game.cardsDiscard(cards).set('outRange',true).fromRenku=true;
						}
						game.updateRenku();
					}
					"step 5"
					var evt=event.getParent();
					if((evt.name!='discard'&&event.type!='discard')&&(evt.name!='loseToDiscardpile'&&event.type!='loseToDiscardpile')) return;
					if(event.animate===false||event.delay===false) return;
					if(evt.delay!=false){
						if(evt.waitingForTransition){
							_status.waitingForTransition=evt.waitingForTransition;
							game.pause();
						}
						else{
							game.delayx();
						}
					}
				},
				damage:function(){
					"step 0"
					event.forceDie=true;
					if(event.unreal) event.goto(4)
					event.trigger('damageBegin1');
					"step 1"
					event.trigger('damageBegin2');
					"step 2"
					event.trigger('damageBegin3');
					"step 3"
					event.trigger('damageBegin4');
					"step 4"
					//moved changeHujia to changeHp
					if(['fire','thunder','ice'].contains(event.nature)){
						if(player.hujia>0&&!player.hasSkillTag('nohujia')&&event.nature!='ice'){
							game.broadcastAll(function(num){
								if(lib.config.background_audio) game.playAudio('effect','hujia_damage_'+event.nature+(num>1?'2':''));
							},num);
						}
						else{
							game.broadcastAll(function(num){
								if(lib.config.background_audio) game.playAudio('effect','damage_'+event.nature+(num>1?'2':''));
							},num);
						}
					}
					else{
						if(player.hujia>0&&!player.hasSkillTag('nohujia')){
							game.broadcastAll(function(num){
								if(lib.config.background_audio) game.playAudio('effect','hujia_damage'+(num>1?'2':''));
							},num);
						}
						else{
							game.broadcastAll(function(num){
								if(lib.config.background_audio) game.playAudio('effect','damage'+(num>1?'2':''));
							},num);
						}
					}
					var str=event.unreal?'视为受到了':'受到了';
					if(source) str+='来自<span class="bluetext">'+(source==player?'自己':get.translation(source))+'</span>的';
					str+=get.cnNumber(num)+'点';
					if(event.nature) str+=get.translation(event.nature)+'属性';
					str+='伤害';
					game.log(player,str);
					if(player.stat[player.stat.length-1].damaged==undefined){
						player.stat[player.stat.length-1].damaged=num;
					}
					else{
						player.stat[player.stat.length-1].damaged+=num;
					}
					if(source){
						source.getHistory('sourceDamage').push(event);
						if(source.stat[source.stat.length-1].damage==undefined){
							source.stat[source.stat.length-1].damage=num;
						}
						else{
							source.stat[source.stat.length-1].damage+=num;
						}
					}
					player.getHistory('damage').push(event);
					if(!event.unreal){
						if(event.notrigger){
							player.changeHp(-num,false)._triggered=null;
						}
						else{
							player.changeHp(-num,false);
						}
					}
					if(event.animate!==false){
						player.$damage(source);
						var natures=(event.nature||'').split(lib.natureSeparator);
						game.broadcastAll(function(natures,player){
							if(lib.config.animation&&!lib.config.low_performance){
								if(natures.includes('fire')){
									player.$fire();
								}
								if(natures.includes('thunder')){
									player.$thunder();
								}
							}
						},natures,player);
						var numx=Math.max(0,num-player.hujia);
						player.$damagepop(-numx,natures[0]);
					}
					if(event.unreal) event.goto(6)
					if(!event.notrigger){
						if(num==0){
							event.trigger('damageZero');
							event._triggered=null;
						}
						else{
							event.trigger('damage');
						}
					}
					"step 5"
					if(player.hp<=0&&player.isAlive()&&!event.nodying){
						game.delayx();
						event._dyinged=true;
						player.dying(event);
					}
					if(source&&lib.config.border_style=='auto'){
						var dnum=0;
						for(var j=0;j<source.stat.length;j++){
							if(source.stat[j].damage!=undefined) dnum+=source.stat[j].damage;
						}
						if(dnum>=2){
							if(lib.config.autoborder_start=='silver'){
								dnum+=4;
							}
							else if(lib.config.autoborder_start=='gold'){
								dnum+=8;
							}
						}
						if(lib.config.autoborder_count=='damage'){
							source.node.framebg.dataset.decoration='';
							if(dnum>=10){
								source.node.framebg.dataset.auto='gold';
								if(dnum>=12) source.node.framebg.dataset.decoration='gold';
							}
							else if(dnum>=6){
								source.node.framebg.dataset.auto='silver';
								if(dnum>=8) source.node.framebg.dataset.decoration='silver';
							}
							else if(dnum>=2){
								source.node.framebg.dataset.auto='bronze';
								if(dnum>=4) source.node.framebg.dataset.decoration='bronze';
							}
							if(dnum>=2){
								source.classList.add('topcount');
							}
						}
						else if(lib.config.autoborder_count=='mix'){
							source.node.framebg.dataset.decoration='';
							switch(source.node.framebg.dataset.auto){
								case 'bronze':if(dnum>=4) source.node.framebg.dataset.decoration='bronze';break;
								case 'silver':if(dnum>=8) source.node.framebg.dataset.decoration='silver';break;
								case 'gold':if(dnum>=12) source.node.framebg.dataset.decoration='gold';break;
							}
						}
					}
					"step 6"
					if(!event.notrigger) event.trigger('damageSource');
				},
				recover:function(){
					if(lib.config.background_audio){
						game.playAudio('effect','recover');
					}
					game.broadcast(function(){
						if(lib.config.background_audio){
							game.playAudio('effect','recover');
						}
					});
					if(num>player.maxHp-player.hp){
						num=player.maxHp-player.hp;
						event.num=num;
					}
					if(num>0){
						player.changeHp(num,false);
						game.broadcastAll(function(player){
							if(lib.config.animation&&!lib.config.low_performance){
								player.$recover();
							}
						},player);
						player.$damagepop(num,'wood');
						game.log(player,'回复了'+get.cnNumber(num)+'点体力')
					}
				},
				loseHp:function(){
					"step 0"
					if(lib.config.background_audio){
						game.playAudio('effect','loseHp');
					}
					game.broadcast(function(){
						if(lib.config.background_audio){
							game.playAudio('effect','loseHp');
						}
					});
					game.log(player,'失去了'+get.cnNumber(num)+'点体力')
					player.changeHp(-num);
					"step 1"
					if(player.hp<=0&&!event.nodying){
						game.delayx();
						event._dyinged=true;
						player.dying(event);
					}
				},
				doubleDraw:function(){
					"step 0"
					player.chooseBool('你的主副将体力上限之和是奇数,是否摸一张牌?');
					"step 1"
					if(result.bool){
						player.draw();
					}
				},
				loseMaxHp:function(){
					"step 0"
					game.log(player,'减少了'+get.cnNumber(num)+'点体力上限');
					player.maxHp-=num;
					event.loseHp=Math.max(0,player.hp-player.maxHp);
					player.update();
					"step 1"
					if(player.maxHp<=0){
						player.die(event);
					}
				},
				gainMaxHp:function(){
					"step 0"
					game.log(player,'增加了'+get.cnNumber(num)+'点体力上限');
					player.maxHp+=num;
					player.update();
				},
				changeHp:function(){
					//add to GlobalHistory
					game.getGlobalHistory().changeHp.push(event);
					//changeHujia moved here
					if(num<0&&player.hujia>0&&event.getParent().name=='damage'&&!player.hasSkillTag('nohujia')){
						event.hujia=Math.min(-num,player.hujia);
						event.getParent().hujia=event.hujia;
						event.num+=event.hujia;
						game.log(player,'的护甲抵挡了'+get.cnNumber(event.hujia)+'点伤害');
						player.changeHujia(-event.hujia).type='damage';
					}
					//old part
					num=event.num;
					player.hp+=num;
					if(isNaN(player.hp)) player.hp=0;
					if(player.hp>player.maxHp) player.hp=player.maxHp;
					player.update();
					if(event.popup!==false){
						player.$damagepop(num,'water');
					}
					if(_status.dying.contains(player)&&player.hp>0){
						_status.dying.remove(player);
						game.broadcast(function(list){
							_status.dying=list;
						},_status.dying);
						var evt=event.getParent('_save');
						if(evt&&evt.finish) evt.finish();
						evt=event.getParent('dying');
						if(evt&&evt.finish) evt.finish()
					}
					event.trigger('changeHp');
				},
				changeHujia:function(){
					player.hujia+=num;
					if(num>0){
						game.log(player,'获得了'+get.cnNumber(num)+'点护甲');
					}
					if(player.hujia<0){
						player.hujia=0;
					}
					player.update();
				},
				dying:function(){
					"step 0"
					event.forceDie=true;
					if(player.isDying()||player.hp>0){
						event.finish();
						return;
					}
					_status.dying.unshift(player);
					game.broadcast(function(list){
						_status.dying=list;
					},_status.dying);
					event.trigger('dying');
					game.log(player,'濒死');
					"step 1"
					delete event.filterStop;
					if(player.hp>0||event.nodying){
						_status.dying.remove(player);
						game.broadcast(function(list){
							_status.dying=list;
						},_status.dying);
						event.finish();
					}
					else if(!event.skipTao){
						var next=game.createEvent('_save');
						var start=false;
						var starts=[_status.currentPhase,event.source,event.player,game.me,game.players[0]];
						for(var i=0;i<starts.length;i++){
							if(get.itemtype(starts[i])=='player'){
								start=starts[i];break;
							}
						}
						next.player=start;
						next._trigger=event;
						next.triggername='_save';
						next.forceDie=true;
						next.setContent(lib.skill._save.content);
					}
					"step 2"
					_status.dying.remove(player);
					game.broadcast(function(list){
						_status.dying=list;
					},_status.dying);
					if(player.hp<=0&&!event.nodying&&!player.nodying) player.die(event.reason);
				},
				die:function(){
					"step 0"
					event.forceDie=true;
					if(_status.roundStart==player){
						_status.roundStart=player.next||player.getNext()||game.players[0];
					}
					if(ui.land&&ui.land.player==player){
						game.addVideo('destroyLand');
						ui.land.destroy();
					}
					var unseen=false;
					if(player.classList.contains('unseen')){
						player.classList.remove('unseen');
						unseen=true;
					}
					var logvid=game.logv(player,'die',source);
					event.logvid=logvid;
					if(unseen){
						player.classList.add('unseen');
					}
					if(source){
						game.log(player,'被',source,'杀害');
						if(source.stat[source.stat.length-1].kill==undefined){
							source.stat[source.stat.length-1].kill=1;
						}
						else{
							source.stat[source.stat.length-1].kill++;
						}
					}
					else{
						game.log(player,'阵亡')
					}
					
					
					// player.removeEquipTrigger();
					
					// for(var i in lib.skill.globalmap){
					//     if(lib.skill.globalmap[i].contains(player)){
					//      			lib.skill.globalmap[i].remove(player);
					//      			if(lib.skill.globalmap[i].length==0&&!lib.skill[i].globalFixed){
					//      						 game.removeGlobalSkill(i);
					//      			}
					//     }
					// }
					game.broadcastAll(function(player){
						player.classList.add('dead');
						player.removeLink();
						player.classList.remove('turnedover');
						player.classList.remove('out');
						player.node.count.innerHTML='0';
						player.node.hp.hide();
						player.node.equips.hide();
						player.node.count.hide();
						player.previous.next=player.next;
						player.next.previous=player.previous;
						game.players.remove(player);
						game.dead.push(player);
						_status.dying.remove(player);

						if(lib.config.background_speak){
							if(lib.character[player.name]&&lib.character[player.name][4].some(tag=>/^die:.+$/.test(tag))){
								var tag=lib.character[player.name][4].find(tag=>/^die:.+$/.test(tag));
								var reg=new RegExp("^ext:(.+)?/");
								var match=tag.match(/^die:(.+)$/);
								if(match){
									var path=match[1];
									if(reg.test(path)) path=path.replace(reg,(_o,p)=>`../extension/${p}/`);
									game.playAudio(path);
								}
							}
							else if(lib.character[player.name]&&lib.character[player.name][4].contains('die_audio')){
								game.playAudio('die',player.name);
							}
							else{
								game.playAudio('die',player.name,function(){
									game.playAudio('die',player.name.slice(player.name.indexOf('_')+1));
								});
							}
						}
					},player);

					game.addVideo('diex',player);
					if(event.animate!==false){
						player.$die(source);
					}
					if(player.hp!=0){
						player.changeHp(0-player.hp,false).forceDie=true;
					}
					"step 1"
					if(player.dieAfter) player.dieAfter(source);
					"step 2"
					event.trigger('die');
					"step 3"
					if(player.isDead()){
						if(!game.reserveDead){
							for(var mark in player.marks){
								player.unmarkSkill(mark);
							}
							while(player.node.marks.childNodes.length>1){
								player.node.marks.lastChild.remove();
							}
							game.broadcast(function(player){
								while(player.node.marks.childNodes.length>1){
									player.node.marks.lastChild.remove();
								}
							},player);
						}
						for(var i in player.tempSkills){
							player.removeSkill(i);
						}
						var skills=player.getSkills();
						for(var i=0;i<skills.length;i++){
							if(lib.skill[skills[i]].temp){
								player.removeSkill(skills[i]);
							}
						}
						if(_status.characterlist){
							if(lib.character[player.name]&&!player.name.startsWith('gz_shibing')&&!player.name.startsWith('gz_jun_')) _status.characterlist.add(player.name);
							if(lib.character[player.name1]&&!player.name1.startsWith('gz_shibing')&&!player.name1.startsWith('gz_jun_')) _status.characterlist.add(player.name1);
							if(lib.character[player.name2]&&!player.name2.startsWith('gz_shibing')&&!player.name2.startsWith('gz_jun_')) _status.characterlist.add(player.name2);
						}
						event.cards=player.getCards('hejsx');
						if(event.cards.length){
							player.discard(event.cards).forceDie=true;
							//player.$throw(event.cards,1000);
						}
					}
					"step 4"
					if(player.dieAfter2) player.dieAfter2(source);
					"step 5"
					game.broadcastAll(function(player){
						if(game.online&&player==game.me&&!_status.over&&!game.controlOver&&!ui.exit){
							if(lib.mode[lib.configOL.mode].config.dierestart){
								ui.create.exit();
							}
						}
					},player);
					if(!_status.connectMode&&player==game.me&&!_status.over&&!game.controlOver){
						ui.control.show();
						if(get.config('revive')&&lib.mode[lib.config.mode].config.revive&&!ui.revive){
							ui.revive=ui.create.control('revive',ui.click.dierevive);
						}
						if(get.config('continue_game')&&!ui.continue_game&&lib.mode[lib.config.mode].config.continue_game&&!_status.brawl&&!game.no_continue_game){
							ui.continue_game=ui.create.control('再战',game.reloadCurrent);
						}
						if(get.config('dierestart')&&lib.mode[lib.config.mode].config.dierestart&&!ui.restart){
							ui.restart=ui.create.control('restart',game.reload);
						}
					}

					if(!_status.connectMode&&player==game.me&&!game.modeSwapPlayer){
						// _status.auto=false;
						if(ui.auto){
							// ui.auto.classList.remove('glow');
							ui.auto.hide();
						}
						if(ui.wuxie) ui.wuxie.hide();
					}
					
					if(typeof _status.coin=='number'&&source&&!_status.auto){
						if(source==game.me||source.isUnderControl()){
							_status.coin+=10;
						}
					}
					if(source&&lib.config.border_style=='auto'&&(lib.config.autoborder_count=='kill'||lib.config.autoborder_count=='mix')){
						switch(source.node.framebg.dataset.auto){
							case 'gold':case 'silver':source.node.framebg.dataset.auto='gold';break;
							case 'bronze':source.node.framebg.dataset.auto='silver';break;
							default:source.node.framebg.dataset.auto=lib.config.autoborder_start||'bronze';
						}
						if(lib.config.autoborder_count=='kill'){
							source.node.framebg.dataset.decoration=source.node.framebg.dataset.auto;
						}
						else{
							var dnum=0;
							for(var j=0;j<source.stat.length;j++){
								if(source.stat[j].damage!=undefined) dnum+=source.stat[j].damage;
							}
							source.node.framebg.dataset.decoration='';
							switch(source.node.framebg.dataset.auto){
								case 'bronze':if(dnum>=4) source.node.framebg.dataset.decoration='bronze';break;
								case 'silver':if(dnum>=8) source.node.framebg.dataset.decoration='silver';break;
								case 'gold':if(dnum>=12) source.node.framebg.dataset.decoration='gold';break;
							}
						}
						source.classList.add('topcount');
					}
				},
				addJudge:function(){
					"step 0"
					if(cards){
						var owner=get.owner(cards[0]);
						if(owner){
							event.relatedLose=owner.lose(cards,'visible',ui.special).set('getlx',false);
						}
						else if(get.position(cards[0])=='c') event.updatePile=true;
					}
					"step 1"
					if(cards[0].destroyed){
						if(player.hasSkill(cards[0].destroyed)){
							delete cards[0].destroyed;
						}
						else{
							event.finish();
							return;
						}
					}
					else if(event.relatedLose){
						var owner=event.relatedLose.player;
						if(owner.getCards('hejsx').contains(card)){
							event.finish();
							return;
						}
					}
					cards[0].fix();
					cards[0].style.transform='';
					cards[0].classList.remove('drawinghidden');
					delete cards[0]._transform;
					var viewAs=typeof card=='string'?card:card.name;
					if(!lib.card[viewAs]||!lib.card[viewAs].effect){
						game.cardsDiscard(cards[0]);
					}
					else{
						cards[0].style.transform='';
						cards[0].classList.add('drawinghidden');
						player.node.judges.insertBefore(cards[0],player.node.judges.firstChild);
						if(_status.discarded){
							_status.discarded.remove(cards[0]);
						}
						ui.updatej(player);
						game.broadcast(function(player,card,viewAs){
							card.fix();
							card.style.transform='';
							card.classList.add('drawinghidden');
							card.viewAs=viewAs;
							if(viewAs&&viewAs!=card.name&&(card.classList.contains('fullskin')||card.classList.contains('fullborder'))){
								card.classList.add('fakejudge');
								card.node.background.innerHTML=lib.translate[viewAs+'_bg']||get.translation(viewAs)[0]
							}
							else{
								card.classList.remove('fakejudge');
							}
							player.node.judges.insertBefore(card,player.node.judges.firstChild);
							ui.updatej(player);
							if(card.clone&&(card.clone.parentNode==player.parentNode||card.clone.parentNode==ui.arena)){
								card.clone.moveDelete(player);
								game.addVideo('gain2',player,get.cardsInfo([card]));
							}
						},player,cards[0],viewAs);
						if(cards[0].clone&&(cards[0].clone.parentNode==player.parentNode||cards[0].clone.parentNode==ui.arena)){
							cards[0].clone.moveDelete(player);
							game.addVideo('gain2',player,get.cardsInfo(cards));
						}
						// player.$gain2(cards);
						if(get.itemtype(card)!='card'){
							if(typeof card=='string') cards[0].viewAs=card;
							else cards[0].viewAs=card.name;
						}
						else{
							delete cards[0].viewAs;
						}
						if(cards[0].viewAs&&cards[0].viewAs!=cards[0].name){
							if(cards[0].classList.contains('fullskin')||cards[0].classList.contains('fullborder')){
								cards[0].classList.add('fakejudge');
								cards[0].node.background.innerHTML=lib.translate[cards[0].viewAs+'_bg']||get.translation(cards[0].viewAs)[0];
							}
							game.log(player,'被贴上了<span class="yellowtext">'+get.translation(cards[0].viewAs)+'</span>(',cards,')');
						}
						else{
							cards[0].classList.remove('fakejudge');
							game.log(player,'被贴上了',cards);
						}
						game.addVideo('addJudge',player,[get.cardInfo(cards[0]),cards[0].viewAs]);
					}
					if(event.updatePile) game.updateRoundNumber();
				},
				judge:function(){
					"step 0"
					var judgestr=get.translation(player)+'的'+event.judgestr+'判定';
					event.videoId=lib.status.videoId++;
					var cardj=event.directresult;
					if(!cardj){
						if(player.getTopCards) cardj=player.getTopCards()[0];
						else cardj=get.cards()[0];
					}
					var owner=get.owner(cardj);
					if(owner){
						owner.lose(cardj,'visible',ui.ordering);
					}
					else{
						var nextj=game.cardsGotoOrdering(cardj);
						if(event.position!=ui.discardPile) nextj.noOrdering=true;
					}
					player.judging.unshift(cardj);
					game.addVideo('judge1',player,[get.cardInfo(player.judging[0]),judgestr,event.videoId]);
					game.broadcastAll(function(player,card,str,id,cardid){
						var event;
						if(game.online){
							event={};
						}
						else{
							event=_status.event;
						}
						if(game.chess){
							event.node=card.copy('thrown','center',ui.arena).animate('start');
						}
						else{
							event.node=player.$throwordered(card.copy(),true);
						}
						if(lib.cardOL) lib.cardOL[cardid]=event.node;
						event.node.cardid=cardid;
						event.node.classList.add('thrownhighlight');
						ui.arena.classList.add('thrownhighlight');
						event.dialog=ui.create.dialog(str);
						event.dialog.classList.add('center');
						event.dialog.videoId=id;
					},player,player.judging[0],judgestr,event.videoId,get.id());

					game.log(player,'进行'+event.judgestr+'判定,亮出的判定牌为',player.judging[0]);
					game.delay(2);
					if(!event.noJudgeTrigger) event.trigger('judge');
					"step 1"
					event.result={
						card:player.judging[0],
						name:player.judging[0].name,
						number:get.number(player.judging[0]),
						suit:get.suit(player.judging[0]),
						color:get.color(player.judging[0]),
						node:event.node,
					};
					if(event.fixedResult){
						for(var i in event.fixedResult){
							event.result[i]=event.fixedResult[i];
						}
					}
					event.result.judge=event.judge(event.result);
					if(event.result.judge>0) event.result.bool=true;
					else if(event.result.judge<0) event.result.bool=false;
					else event.result.bool=null;
					player.judging.shift();
					game.checkMod(player,event.result,'judge',player);
					if(event.judge2){
						var judge2=event.judge2(event.result);
						if(typeof judge2=='boolean') player.tryJudgeAnimate(judge2);
					};
					if(event.clearArena!=false){
						game.broadcastAll(ui.clear);
					}
					game.broadcast(function(id){
						var dialog=get.idDialog(id);
						if(dialog){
							dialog.close();
						}
						ui.arena.classList.remove('thrownhighlight');
					},event.videoId);
					event.dialog.close();
					game.addVideo('judge2',null,event.videoId);
					ui.arena.classList.remove('thrownhighlight');
					game.log(player,'的判定结果为',event.result.card);
					event.trigger('judgeFixing');
					if(event.callback){
						var next=game.createEvent('judgeCallback',false);
						next.player=player;
						next.card=event.result.card;
						next.judgeResult=get.copy(event.result);
						next.setContent(event.callback);
					}
					else{
						if(!get.owner(event.result.card)){
							if(event.position!=ui.discardPile) event.position.appendChild(event.result.card);
						}
					}
				},
				turnOver:function(){
					game.log(player,'翻面');
					player.classList.toggle('turnedover');
					game.broadcast(function(player){
						player.classList.toggle('turnedover');
					},player);
					game.addVideo('turnOver',player,player.classList.contains('turnedover'));
				},
				link:function(){
					if(player.isLinked()){
						game.log(player,'解除连环');
					}
					else{
						game.log(player,'被连环');
					}
					if(lib.config.background_audio){
						game.playAudio('effect','link');
					}
					game.broadcast(function(){
						if(lib.config.background_audio){
							game.playAudio('effect','link');
						}
					});
					player.classList.remove('target');
					if(get.is.linked2(player)){
						player.classList.toggle('linked2');
					}
					else{
						player.classList.toggle('linked');
					}
					ui.updatej(player);
					ui.updatem(player);
					game.broadcast(function(player,linked){
						player.classList.remove('target');
						if(get.is.linked2(player)){
							if(linked){
								player.classList.add('linked2');
							}
							else{
								player.classList.remove('linked2');
							}
						}
						else{
							if(linked){
								player.classList.add('linked');
							}
							else{
								player.classList.remove('linked');
							}
						}
						ui.updatej(player);
						ui.updatem(player);
					},player,player.isLinked());
					game.addVideo('link',player,player.isLinked());
				},
				chooseToGuanxing:function(){
					"step 0"
					var cards=get.cards(num);
					game.cardsGotoOrdering(cards);
					var next=player.chooseToMove();
					next.set('list',[
						['牌堆顶',cards],
						['牌堆底'],
					]);
					next.set('prompt','点击将牌移动到牌堆顶或牌堆底');
					next.processAI=event.processAI||function(list){
						var cards=list[0][1],player=_status.event.player;
						var top=[];
						var bottom;
						cards.sort(function(a,b){
							return get.value(b,player)-get.value(a,player);
						});
						while(cards.length){
							if(get.value(cards[0],player)<=5) break;
							top.unshift(cards.shift());
						}
						bottom=cards;
						return [top,bottom];
					};
					"step 1"
					var top=result.moved[0];
					var bottom=result.moved[1];
					top.reverse();
					for(var i=0;i<top.length;i++){
						ui.cardPile.insertBefore(top[i],ui.cardPile.firstChild);
					}
					for(i=0;i<bottom.length;i++){
						ui.cardPile.appendChild(bottom[i]);
					}
					player.popup(get.cnNumber(top.length)+'上'+get.cnNumber(bottom.length)+'下');
					game.log(player,'将'+get.cnNumber(top.length)+'张牌置于牌堆顶');
					game.updateRoundNumber();
					game.delayx();
				},
			},
			player:{
				//新函数
				/**
				 * version 1.4
				 * 
				 * 链式创建一次性技能的api。
				 *
				 * 使用者只需要关注技能的效果,而不是技能的本身。
				 */
				when:function(){
					if(!_status.postReconnect.player_when) _status.postReconnect.player_when=[
						function(map){
							"use strict";
							for(let i in map){
								lib.skill[i]={
									charlotte:true,
									forced:true,
									popup:false,
								}
								if(typeof map[i]=='string') lib.translate[i]=map[i];
							}
						},{}
					];
					let triggerNames=Array.from(arguments);
					let trigger;
					if(triggerNames.length==0) throw 'player.when的参数数量应大于0';
					//add other triggerNames
					//arguments.length = 1
					if(triggerNames.length==1){
						//以下两种情况:
						//triggerNames = [ ['xxAfter', ...args] ]
						//triggerNames = [ 'xxAfter' ]
						if(Array.isArray(triggerNames[0])||typeof triggerNames[0]=='string') trigger={player:triggerNames[0]};
						//triggerNames = [ {player:'xxx'} ]
						else if(get.is.object(triggerNames[0])) trigger=triggerNames[0];
					}
					//arguments.length > 1
					else{
						//triggerNames = [ 'xxAfter', 'yyBegin' ]
						if(triggerNames.every(t=>typeof t=='string')) trigger={player:triggerNames};
						//triggerNames = [ {player: 'xxAfter'}, {global: 'yyBegin'} ]
						//此处不做特殊的合并处理,由使用者自行把握
						else if(triggerNames.every(t=>get.is.object(t))) trigger=triggerNames.reduce((pre,cur)=>Object.assign(pre,cur));
					}
					if(!trigger) throw 'player.when传参数类型错误:'+triggerNames;
					let skillName;
					do{
						skillName='player_when_'+Math.random().toString(36).slice(-8);
					}while(lib.skill[skillName]!=null);
					let after=`${skillName}After`;
					if(!trigger.player) trigger.player=after;
					else if(Array.isArray(trigger.player)) trigger.player.add(after);
					else if(typeof trigger.player=='string') trigger.player=[trigger.player,after];
					let skill={
						trigger,
						forced:true,
						charlotte:true,
						popup:false,
						//必要条件
						filterFuns:[],
						//充分条件
						filter2Funs:[],
						contentFuns:[],
						get filter(){
							return (event,player,name)=>{
								if(name==`${skillName}After`){
									skill.popup=false;
									return true;
								}
								return skill.filterFuns.every(fun=>Boolean(fun(event,player,name)))&&
									skill.filter2(event,player,name);
							}
						},
						get filter2(){
							return (event,player,name)=>{
								return skill.filter2Funs.length==0||
								skill.filter2Funs.some(fun=>Boolean(fun(event,player,name)));
							};
						}
					};
					Object.defineProperty(lib.skill,skillName,{
						configurable:true,
						//这类技能不需要被遍历到
						enumerable:false,
						writable:true,
						value:skill
					});
					game.broadcast(function(skillName){
						Object.defineProperty(lib.skill,skillName,{
							configurable:true,
							enumerable:false,
							writable:true,
							value:{
								forced:true,
								charlotte:true,
								popup:false,
							}
						});
					},skillName);
					this.addSkill(skillName);
					_status.postReconnect.player_when[1][skillName]=true;
					return{
						filter(fun){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							skill.filterFuns.push(fun);
							return this;
						},
						removeFilter(fun){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							skill.filterFuns.remove(fun);
							return this;
						},
						filter2(fun){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							skill.filter2Funs.push(fun);
							return this;
						},
						removeFilter2(fun){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							skill.filter2Funs.remove(fun);
							return this;
						},
						then(fun){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							skill.contentFuns.push(fun);
							let str=`
								function content(){
									if(event.triggername=='${skillName}After'){
										player.removeSkill('${skillName}');
										delete lib.skill['${skillName}'];
										delete lib.translate['${skillName}'];
										return event.finish();
									}
							`;
							for(let i=0;i<skill.contentFuns.length;i++){
								let fun2=skill.contentFuns[i];
								let a=fun2.toString();
								let str2=a.slice(a.indexOf("{")+1,a.lastIndexOf("}")!=-1?a.lastIndexOf("}"):undefined).trim();
								str+=`'step ${i}'\n\t${str2}\n\t`;
							}
							let result=eval(str+`\n};content;`);
							skill.content=result;
							return this;
						},
						popup(str){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							if(typeof str=='string') skill.popup=str;
							return this;
						},
						translation(translation){
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							if(typeof translation=='string'){
								_status.postReconnect.player_when[1][skillName]=translation;
								game.broadcastAll((skillName,translation)=>lib.translate[skillName]=translation,skillName,translation)
							}
							return this;
						},
						assign(obj) {
							if(lib.skill[skillName]!=skill) throw `This skill has been destroyed`;
							if(typeof obj=='object'&&obj!==null) Object.assign(skill,obj);
							return this;
						}
					};
				},
				//让一名角色明置一些手牌
				addShownCards:function(){
					const cards=[],tags=[];
					for(const argument of arguments){
						const type=get.itemtype(argument);
						if(type=='cards') cards.addArray(argument);
						else if(type=='card') cards.add(argument);
						else if(typeof argument=='string'&&argument.startsWith('visible_')) tags.add(argument);
					}
					if(!cards.length||!tags.length) return;
					const next=game.createEvent('addShownCards',false);
					next.player=this;
					next._cards=cards;
					next.gaintag=tags;
					next.setContent('addShownCards');
					return next;
				},
				hideShownCards:function(){
					const cards=[],tags=[];
					for(const argument of arguments){
						const type=get.itemtype(argument);
						if(type=='cards') cards.addArray(argument);
						else if(type=='card') cards.add(argument);
						else if(typeof argument=='string'&&argument.startsWith('visible_')) tags.add(argument);
					}
					if(!cards.length) return;
					const next=game.createEvent('hideShownCards',false);
					next.player=this;
					next._cards=cards;
					next.gaintag=tags;
					next.setContent('hideShownCards');
					return next;
				},
				//获取角色所有的明置手牌
				getShownCards:function(){
					return this.getCards('h',function(card){
						return get.is.shownCard(card);
					});
				},
				//Execute the delay card effect
				//执行延时锦囊牌效果
				executeDelayCardEffect:function(card,target,judge,judge2){
					const executeDelayCardEffect=game.createEvent('executeDelayCardEffect');
					executeDelayCardEffect.player=this;
					executeDelayCardEffect.target=target||this;
					if(typeof card=='string'){
						const virtualCard=executeDelayCardEffect.card=ui.create.card();
						virtualCard._destroy=true;
						virtualCard.expired=true;
						const info=lib.card[card];
						virtualCard.init(['','',card,info&&info.cardnature]);
					}
					else if(get.itemtype(card)=='card') executeDelayCardEffect.card=card;
					else _status.event.next.remove(executeDelayCardEffect);
					executeDelayCardEffect.judge=judge;
					executeDelayCardEffect.judge2=judge2;
					executeDelayCardEffect.setContent('executeDelayCardEffect');
					executeDelayCardEffect._args=Array.from(arguments);
					return executeDelayCardEffect;
				},
				//Check if the card does not count toward hand limit
				//检测此牌是否不计入手牌上限
				canIgnoreHandcard:function(card){
					return lib.filter.ignoredHandcard(card,this);
				},
				//Gift
				//赠予
				gift:function(cards,target){
					const gift=game.createEvent('gift');
					gift.player=this;
					gift.target=target;
					const isArray=Array.isArray(cards);
					if(cards&&!isArray) gift.cards=[cards];
					else if(isArray&&cards.length) gift.cards=cards;
					else _status.event.next.remove(gift);
					gift.deniedGifts=[];
					gift.setContent('gift');
					gift._args=Array.from(arguments);
					return gift;
				},
				//Check if the player can gift the card
				//检测角色是否能赠予此牌
				canGift:function(card,target,strict){
					return lib.filter.cardGiftable(card,this,target,strict);
				},
				//Check if the player refuses gifts
				//检测角色是否拒绝赠予
				refuseGifts:function(card,player){
					return this.hasSkillTag('refuseGifts',null,{
						player:player,
						card:card
					});
				},
				//Gift AI related
				//赠予AI相关
				getGiftAIResultTarget:function(card,target){
					if(!card||target.refuseGifts(card,this)) return 0;
					if(get.type(card,false)=='equip') return get.effect(target,card,target,target);
					if(card.name=='du') return this.hp>target.hp?-1:0;
					if(target.hasSkillTag('nogain')) return 0;
					return Math.max(1,get.value(card,this)-get.value(card,target));
				},
				getGiftEffect:function(card,target){
					return this.getGiftAIResultTarget(card,target)*get.attitude(this,target);
				},
				//Recast
				//重铸
				recast:function(cards,recastingLose,recastingGain){
					const recast=game.createEvent('recast');
					recast.player=this;
					const isArray=Array.isArray(cards);
					if(cards&&!isArray) recast.cards=[cards];
					else if(isArray&&cards.length) recast.cards=cards;
					else _status.event.next.remove(recast);
					if(typeof recastingLose!='function') recastingLose=(player,cards)=>player.loseToDiscardpile(cards).log=false;
					recast.recastingLose=recastingLose;
					recast.recastingLosingEvents=[];
					if(typeof recastingGain!='function') recastingGain=(player,cards)=>player.draw(cards.length).log=false;
					recast.recastingGain=recastingGain;
					recast.recastingGainingEvents=[];
					recast.setContent('recast');
					recast._args=Array.from(arguments);
					return recast;
				},
				//Check if the player can recast the card
				//检测角色是否能重铸此牌
				canRecast:function(card,source,strict){
					return lib.filter.cardRecastable(card,this,source,strict);
				},
				//装备栏相关
				//判断一名角色的某个区域是否被废除
				//type为要判断的区域 若为空 则判断玩家是否有任意一个被废除的区域
				hasDisabledSlot:function(type){
					var player=this;
					if(type=='horse') return player.hasDisabledSlot(3)&&player.hasDisabledSlot(4);
					return player.countDisabledSlot(type)>0;
				},
				//判断一名角色的某个区域被废除的数量
				//用法同上
				countDisabledSlot:function(type){
					var player=this;
					var map=(player.disabledSlots||{});
					if(type==undefined){
						num=0;
						for(var i=1;i<=5;i++){
							num+=player.countDisabledSlot(i);
						}
						return num;
					}
					else{
						if(typeof type=='number') type=('equip'+type);
						var num=map[type];
						if(typeof num=='number'&&num>0) return num;
						return 0;
					}
				},
				//判断一名角色是否有某个装备栏空着
				hasEmptySlot:function(type){
					var player=this;
					if(type=='horse') return player.hasEmptySlot(3)&&player.hasEmptySlot(4);
					return player.countEmptySlot(type)>0;
				},
				//判断一名角色的某个装备栏空位的数量
				countEmptySlot:function(type){
					if(!type) return 0;
					var player=this;
					if(typeof type=='number') type=('equip'+type);
					return Math.max(0,player.countEnabledSlot(type)-player.getEquips(type).reduce(function(num,card){
						var types=get.subtypes(card,false);
						return num+get.numOf(types,type);
					},0))
				},
				//判断一名角色是否有可以用于装备新装备牌的区域(排除金箍棒和六龙等“不可被替换装备”)
				//用法同下
				hasEquipableSlot:function(type){
					return this.countEquipableSlot(type)>0;
				},
				//统计一名角色有多少个可以用于装备新的装备牌的区域
				//用法同下
				countEquipableSlot:function(type){
					if(!type) return 0;
					var player=this;
					if(typeof type=='number') type=('equip'+type);
					return Math.max(0,player.countEnabledSlot(type)-player.getEquips(type).reduce(function(num,card){
						var types=get.subtypes(card,false);
						if(!lib.filter.canBeReplaced(card,player)) num+=get.numOf(types,type);
						return num;
					},0))
				},
				//判断一名角色是否拥有未被废除的某个区域
				//type为要判断的区域 若为空 则判断玩家是否有任意一个未被废除的区域
				hasEnabledSlot:function(type){
					var player=this;
					if(type=='horse') return player.hasEnabledSlot(3)&&player.hasEnabledSlot(4);
					return player.countEnabledSlot(type)>0;
				},
				//判断一名角色的某个区域未被废除的数量
				//用法同上
				countEnabledSlot:function(type){
					var player=this;
					var map=(player.expandedSlots||{});
					if(!type){
						num=0;
						for(var i=1;i<=5;i++){
							num+=player.countEnabledSlot(i);
						}
						return num;
					}
					else{
						if(typeof type=='number') type=('equip'+type);
						var slots=1;
						var num=map[type];
						if(typeof num=='number'&&num>0) slots+=num;
						slots-=player.countDisabledSlot(type);
						return slots;
					}
				},
				//获取一名角色装备区内某种类型的装备牌
				//参数可以为数字/区域字符串/实体牌/虚拟牌/牌名
				getEquips:function(subtype){
					var type=(typeof subtype);
					switch(type){
						case 'string':
							if(subtype.startsWith('equip')&&parseInt(subtype.slice(5))>0){
								break;
							}
							else if(lib.card[subtype]){
								return this.getCards('e',card=>card.name==subtype);
							}
							else return [];
						case 'number':
							subtype='equip'+subtype;
							break;
						case 'object':
							subtype=get.subtype(subtype,false);
							break;
						default:
							return [];
					}
					if(!subtype) return [];
					return this.getCards('e',function(card){
						return get.subtypes(card,false).contains(subtype);
					})
				},
				//新的废除装备区/恢复装备区/扩展装备区
				//参数:废除来源角色(不写默认当前事件角色),废除区域(数字/区域字符串/数组,可以写多个,重复废除)
				disableEquip:function(){
					var next=game.createEvent('disableEquip');
					next.player=this;
					next.slots=[];
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(Array.isArray(arguments[i])){
							for(var arg of arguments[i]){
								if(typeof arg=='string'){
									if(arg.startsWith('equip')&&parseInt(arg.slice(5))>0) next.slots.push(arg);
								}
								else if(typeof arg=='number'){
									next.slots.push('equip'+arg);
								}
							}
						}
						else if(typeof arguments[i]=='string'){
							if(arguments[i].startsWith('equip')&&parseInt(arguments[i].slice(5))>0) next.slots.push(arguments[i]);
						}
						else if(typeof arguments[i]=='number'){
							next.slots.push('equip'+arguments[i]);
						}
					}
					if(!next.source) next.source=_status.event.player;
					if(!next.slots.length){
						_status.event.next.remove(next);
					}
					next.setContent('disableEquip');
					return next;
				},
				enableEquip:function(){
					var next=game.createEvent('enableEquip');
					next.player=this;
					next.slots=[];
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(Array.isArray(arguments[i])){
							for(var arg of arguments[i]){
								if(typeof arg=='string'){
									if(arg.startsWith('equip')&&parseInt(arg.slice(5))>0) next.slots.push(arg);
								}
								else if(typeof arg=='number'){
									next.slots.push('equip'+arg);
								}
							}
						}
						else if(typeof arguments[i]=='string'){
							if(arguments[i].startsWith('equip')&&parseInt(arguments[i].slice(5))>0) next.slots.push(arguments[i]);
						}
						else if(typeof arguments[i]=='number'){
							next.slots.push('equip'+arguments[i]);
						}
					}
					if(!next.source) next.source=_status.event.player;
					if(!next.slots.length){
						_status.event.next.remove(next);
					}
					next.setContent('enableEquip');
					return next;
				},
				expandEquip:function(){
					var next=game.createEvent('expandEquip');
					next.player=this;
					next.slots=[];
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(Array.isArray(arguments[i])){
							for(var arg of arguments[i]){
								if(typeof arg=='string'){
									if(arg.startsWith('equip')&&parseInt(arg.slice(5))>0) next.slots.push(arg);
								}
								else if(typeof arg=='number'){
									next.slots.push('equip'+arg);
								}
							}
						}
						else if(typeof arguments[i]=='string'){
							if(arguments[i].startsWith('equip')&&parseInt(arguments[i].slice(5))>0) next.slots.push(arguments[i]);
						}
						else if(typeof arguments[i]=='number'){
							next.slots.push('equip'+arguments[i]);
						}
					}
					if(!next.source) next.source=_status.event.player;
					if(!next.slots.length){
						_status.event.next.remove(next);
					}
					next.setContent('expandEquip');
					return next;
				},
				//判断判定区是否被废除
				isDisabledJudge:function(){
					return Boolean(this.storage._disableJudge);
				},
				//同步显示扩展装备区状态
				$syncExpand:function(map){
					var player=this;
					if(!map){
						map=(player.expandedSlots||{});
					}
					game.addVideo('$syncExpand',player,get.copy(map))
					game.broadcast(function(player,map){
						player.expandedSlots=map;
						player.$syncExpand(map);
					},player,map);
					player.markSkill('expandedSlots');
				},
				//同步装备区废除牌显示状态
				$syncDisable:function(map){
					var player=this;
					var suits={equip3:'+1马栏',equip4:'-1马栏',equip6:'特殊栏'};
					if(!map){
						map=(player.disabledSlots||{});
					}
					game.addVideo('$syncDisable',player,get.copy(map))
					game.broadcast(function(player,map){
						player.disabledSlots=map;
						player.$syncDisable(map);
					},player,map)
					var map2=get.copy(map);
					var cards=Array.from(player.node.equips.childNodes);
					for(var card of cards){
						if(card.name.startsWith('feichu_')){
							var index=card.name.slice(7);
							if(!map2[index]) map2[index]=0;
							map2[index]--;
						}
					}
					for(var index in map2){
						if(!index.startsWith('equip')||!(parseInt(index.slice(5))>0)) continue;
						var num=map2[index];
						if(num>0){
							for(var i=0;i<num;i++){
								var card=game.createCard('feichu_'+index,(suits[index]||(get.translation(index)+'栏')),'');
								card.fix();
								card.style.transform='';
								card.classList.remove('drawinghidden');
								card.classList.add('feichu');
								delete card._transform;
								var equipNum=get.equipNum(card);
								var equipped=false;
								for(var j=0;j<player.node.equips.childNodes.length;j++){
									if(get.equipNum(player.node.equips.childNodes[j])>=equipNum){
										player.node.equips.insertBefore(card,player.node.equips.childNodes[j]);
										equipped=true;
										break;
									}
								}
								if(!equipped){
									player.node.equips.appendChild(card);
									if(_status.discarded){
										_status.discarded.remove(card);
									}
								}
							}
						}
						else if(num<0){
							for(var i=0;i>num;i--){
								var card=cards.find(card=>card.name=='feichu_'+index);
								if(card){
									player.node.equips.removeChild(card);
									cards.remove(card);
								}
							}
						}
					}
				},
				//以下函数涉及到本次更新内容而进行修改
				canEquip:function(name,replace){
					var ranges=get.subtypes(name),rangex=[...new Set(ranges)],player=this;
					for(var range of rangex){
						var num=this.countEquipableSlot(range);
						var num2=get.numOf(rangex,range);
						if(!replace) num-=this.getEquips(range).filter(card=>lib.filter.canBeReplaced(card,player)).length;
						if(num<num2) return false;
					}
					return true;
				},
				//以下函数将不再进行后续维护
				countDisabled:function(){
					return this.countDisabledSlot.apply(this,arguments)
				},
				isDisabled:function(arg){
					return this.hasDisabledSlot(arg)&&!this.hasEnabledSlot(arg);
				},
				isEmpty:function(num){
					return this.countEnabledSlot(num)>this.getEquips(num).length;
				},
				//以下函数将被废弃
				$disableEquip:function(){},
				$enableEquip:function(){},
				//装备区End
				chooseToDebate:function(){
					var next=game.createEvent('chooseToDebate');
					next.player=this;
					next._args=[];
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='players'){
							next.list=arguments[i].slice(0);
						}
						else{
							next._args.push(arguments[i]);
						}
					}
					next.setContent('chooseToDebate');
					return next;
				},
				cooperationWith:function(target,type,reason){
					var player=this;
					if(!player.storage.cooperation) player.storage.cooperation=[];
					var info={
						target:target,
						type:type,
						reason:reason,
					};
					player.storage.cooperation.add(info);
					player.addTempSkill('cooperation',{player:'dieAfter'});
					player.addSkill('cooperation_'+type,{player:'dieAfter'});
					game.log(player,'向',target,'发起了“协力”,合作类型是','#g'+get.translation('cooperation_'+type));
				},
				chooseCooperationFor:function(){
					var next=game.createEvent('chooseCooperationFor');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.target=arguments[i];
						}
						else if(Array.isArray(arguments[i])){
							next.cardlist=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							next.reason=arguments[i];
						}
					}
					if(!next.cardlist) next.cardlist=['cooperation_damage','cooperation_draw','cooperation_discard','cooperation_use'];
					next.setContent('chooseCooperationFor');
					return next;
				},
				checkCooperationStatus:function(target,reason){
					var storage=this.getStorage('cooperation');
					for(var info of storage){
						if(info.target==target&&info.reason==reason){
							var skill=lib.skill['cooperation_'+info.type];
							if(skill&&skill.checkx&&skill.checkx(info)) return true;
						}
					}
					return false;
				},
				removeCooperation:function(info){
					var player=this;
					var storage=player.getStorage('cooperation');
					if(!storage.contains(info)) return;
					storage.remove(info);
					var unmark=true,reason=info.type;
					if(!storage.length){
						player.removeSkill('cooperation');
					}
					else{
						for(var i of storage){
							if(i.type==reason){
								unmark=false;
								break;
							}
						}
					}
					if(unmark) player.removeSkill('cooperation_'+reason);
					else player.markSkill('cooperation_'+reason);
				},
				hasClan:function(clan,unseen){
					if(unseen||!this.isUnseen(0)){
						var info=lib.character[this.name1];
						if(info&&info[4]){
							for(var i of info[4]){
								if(typeof i=='string'&&i.startsWith('clan:')&&i.slice(5)==clan) return true;
							}
						}
					}
					if(this.name2&&(unseen||!this.isUnseen(1))){
						var info=lib.character[this.name2];
						if(info&&info[4]){
							for(var i of info[4]){
								if(typeof i=='string'&&i.startsWith('clan:')&&i.slice(5)==clan) return true;
							}
						}
					}
					return false;
				},
				changeZhuanhuanji:function(skill){
					var player=this,info=get.info(skill),zhuanhuan=info.zhuanhuanji;
					if(typeof zhuanhuan=='function') zhuanhuan(player,skill);
					else if(zhuanhuan=='number') player.addMark(skill,1,false);
					else player.storage[skill]=!player.storage[skill];
					game.broadcastAll(function(player,skill){
						player.$changeZhuanhuanji(skill);
					},player,skill);
				},
				$changeZhuanhuanji:function(skill){
					var mark=this.marks[skill];
					if(mark){
						if(mark.firstChild.reversed){
							mark.firstChild.reversed=false;
							mark.firstChild.style.transform='none';
						}
						else{
							mark.firstChild.reversed=true;
							mark.firstChild.style.transform='rotate(180deg)';
						}
					}
				},
				setSeatNum:function(num){
					_status.seatNumSettled=true;
					game.broadcastAll(function(player,num){
						player.seatNum=num;
					},this,num);
				},
				getSeatNum:function(){
					if(typeof this.seatNum=='number') return this.seatNum;
					return 0;
				},
				hasSex:function(sex){
					if(this.sex=='unknown') return false;
					if(this.sex=='double') return true;
					return this.sex==sex;
				},
				sameSexAs:function(target){
					var sex1=this.sex,sex2=target.sex;
					if(sex1=='unknown'||sex2=='unknown') return false;
					if(sex1=='double'||sex2=='double') return true;
					return sex1==sex2;
				},
				differentSexFrom:function(target){
					var sex1=this.sex,sex2=target.sex;
					if(sex1=='unknown'||sex2=='unknown') return false;
					if(sex1=='double'||sex2=='double') return true;
					return sex1!=sex2;
				},
				addSkillBlocker:function(skill){
					if(!this.storage.skill_blocker) this.storage.skill_blocker=[];
					this.storage.skill_blocker.push(skill);
				},
				removeSkillBlocker:function(skill){
					if(this.storage.skill_blocker){
						this.storage.skill_blocker.remove(skill);
						if(!this.storage.skill_blocker.length) delete this.storage.skill_blocker;
					}
				},
				loseToSpecial:function(cards,tag,target){
					var next=game.loseAsync({
						player:this,
						cards:cards,
						tag:tag,
						toStorage:true,
						target:target||this,
					});
					next.setContent(function(){
						"step 0"
						player.lose(cards,ui.special).set('getlx',false);
						"step 1"
						var cards=event.cards.slice(0);
						cards.removeArray(player.getCards('hejsx'));
						if(cards.length) target.directgains(cards,null,event.tag)
					});
					return next;
				},
				addGaintag:function(cards,tag){
					if(get.itemtype(cards)=='card') cards=[cards];
					game.addVideo('addGaintag',this,[get.cardsInfo(cards),tag]);
					game.broadcastAll(function(player,cards,tag){
						var hs=player.getCards('hejsx');
						for(var i of cards){
							if(hs.contains(i)) i.addGaintag(tag);
						}
					},this,cards,tag);
				},
				removeGaintag:function(tag,cards){
					cards=cards||this.getCards('h');
					game.addVideo('removeGaintag',this,[tag,get.cardsInfo(cards)]);
					game.broadcastAll(function(player,tag,cards){
						for(var i of cards) i.removeGaintag(tag);
					},this,tag,cards);
				},
				canSave:function(target){
					var player=this;
					if(player.hasSkillTag('save',true,target,true)) return true;
					var name={},hs=player.getCards('hs');
					for(var i of hs) name[get.name(i)]=true;
					for(var i in lib.card){
						if(lib.card[i].savable&&(lib.inpile.contains(i)||name[i])){
							if(lib.filter.cardSavable({name:i},player,target)&&(_status.connectMode||player.hasUsableCard(i))) return true;
						}
					}
					return false;
				},
				canSaveCard:function(card,target){
					var player=this;
					var mod2=game.checkMod(card,player,'unchanged','cardEnabled2',player);
					if(mod2!='unchanged') return mod2;
					var mod=game.checkMod(card,player,target,'unchanged','cardSavable',player);
					if(mod!='unchanged') return mod;
					var savable=get.info(card).savable;
					if(typeof savable=='function') savable=savable(card,player,target);
					return savable;
				},
				showCharacter:function(num,log){
					var toShow=[];
					if((num==0||num==2)&&this.isUnseen(0)) toShow.add(this.name1);
					if((num==1||num==2)&&this.isUnseen(1)) toShow.add(this.name2);
					if(!toShow.length) return;
					lib.element.player.$showCharacter.apply(this,arguments);
					var next=game.createEvent('showCharacter',false);
					next.player=this;
					next.num=num;
					next.toShow=toShow;
					next._args=Array.from(arguments);
					next.setContent('showCharacter');
					var evt=_status.event;
					evt.next.remove(next);
					if(evt.logSkill) evt=evt.getParent();
					evt.after.push(next);
					return next;
				},
				$showCharacter:function(num,log){
					if(num==0&&!this.isUnseen(0)){
						return;
					}
					if(num==1&&(!this.name2||!this.isUnseen(1))){
						return;
					}
					if(!this.isUnseen(2)){
						return;
					}
					game.addVideo('showCharacter',this,num);
					var skills;
					switch(num){
						case 0:
						if(log!==false) game.log(this,'展示了主将','#b'+this.name1);
						this.name=this.name1;
						skills=lib.character[this.name][3]||[];
						this.sex=lib.character[this.name][0];
						if(this.group=='unknown') this.group=lib.character[this.name][1];
						this.classList.remove('unseen');
						break;
						case 1:
						if(log!==false) game.log(this,'展示了副将','#b'+this.name2);
						skills=lib.character[this.name2][3]||[];
						if(this.sex=='unknown') this.sex=lib.character[this.name2][0];
						if(this.name.startsWith('unknown')) this.name=this.name2;
						this.classList.remove('unseen2');
						break;
						case 2:
						if(log!==false){
							if(this.name2) game.log(this,'展示了主将','#b'+this.name1,'、副将','#b'+this.name2);
							else game.log(this,'展示了主将','#b'+this.name1);
						}
						this.name=this.name1;
						var skills=(lib.character[this.name][3]||[]);
						if(this.name2) skills=skills.concat(lib.character[this.name2][3]||[]);
						this.sex=lib.character[this.name][0];
						if(this.group=='unknown') this.group=lib.character[this.name][1];
						this.classList.remove('unseen');
						this.classList.remove('unseen2');
						break;
					}
					if(!this.isUnseen(2)){
						delete this.storage.nohp;
						this.hp=this.storage.rawHp+this.maxHp-1;
						this.maxHp=this.storage.rawMaxHp+this.maxHp-1;
						this.node.hp.show();
						this.update();
					}
					game.broadcast(function(player,name,sex,num,group){
						player.group=group;
						player.name=name;
						player.sex=sex;
						switch(num){
							case 0:player.classList.remove('unseen');break;
							case 1:player.classList.remove('unseen2');break;
							case 2:player.classList.remove('unseen');player.classList.remove('unseen2');break;
						}
						if(!player.isUnseen(2)){
							delete player.storage.nohp;
							player.node.hp.show();
							player.update();
						}
					},this,this.name,this.sex,num,this.group);
					skills=skills.filter(skill=>{
						var info=get.info(skill);
						if(info&&info.zhuSkill&&!this.isZhu2()) return false;
						return true;
					});
					for(var i=0;i<skills.length;i++){
						if(this.hiddenSkills.contains(skills[i])){
							this.hiddenSkills.remove(skills[i]);
							this.addSkill(skills[i]);
						}
					}
					this.checkConflict();
				},
				chooseToPlayBeatmap:function(beatmap){
					var next=game.createEvent('chooseToPlayBeatmap');
					next.player=this;
					next.beatmap=beatmap;
					next._args=Array.from(arguments);
					next.setContent('chooseToPlayBeatmap');
					return next;
				},
				chooseToMove:function(){
					var next=game.createEvent('chooseToMove');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
					}
					next.setContent('chooseToMove');
					next.filterOk=function(){return true};
					next.filterMove=function(){return true};
					return next;
				},
				chooseToGuanxing:function(num){
					var next=game.createEvent('chooseToGuanxing');
					next.num=num||1;
					next.player=this;
					next.setContent('chooseToGuanxing');
					return next;
				},
				$throwEmotion:function(target,name){
					game.addVideo('throwEmotion',this,[target.dataset.position,name]);
					var getLeft=function(player){
						if(player==game.me&&!ui.fakeme&&!ui.chess) return player.getLeft()+player.node.avatar.offsetWidth/2;
						return player.getLeft()+player.offsetWidth/2;
					}
					var player=this;
					var emotion=ui.create.div('','<div style="text-align:center"> <img src="'+lib.assetURL+'image/emotion/throw_emotion/'+name+'1.png"> </div>',game.chess?ui.chess:ui.window);
					emotion.style.width='60px';
					emotion.style.height='60px';
					var width=emotion.offsetWidth/2;
					var height=emotion.offsetHeight/2;
					if(game.chess) width+=60;
					var left=getLeft(player)-width;
					var top=player.getTop()+player.offsetHeight/3-height;
					emotion.style.left=left+'px';
					emotion.style.top=top+'px';
					var left2=getLeft(target)-width;
					var top2=target.getTop()+target.offsetHeight/3-height;
					emotion.style['z-index']=10;
					emotion.style.transform='translateY('+(top2-top)+'px) translateX('+(left2-left)+'px)';
					if(lib.config.background_audio) game.playAudio('effect','throw_'+name+get.rand(1,2));
					setTimeout(function(){
						emotion.innerHTML=('<div style="text-align:center"> <img src="'+lib.assetURL+'image/emotion/throw_emotion/'+name+'2.png"> </div>');
						setTimeout(function(){
							emotion.delete();
						},1200);
					},600);
				},
				tryJudgeAnimate:function(bool){
					var player=this;
					game.broadcast(function(player,bool){
						player.trySkillAnimate(bool);
					},player,bool);
					if(bool) this.popup('判定生效','wood',false);
					else this.popup('判定失效','fire',false);
				},
				trySkillAnimate:function(name,popname,checkShow){
					if(!game.online&&lib.config.skill_animation_type!='off'&&lib.skill[name]&&lib.skill[name].skillAnimation){
						if(lib.config.skill_animation_type=='default'){
							checkShow=checkShow||'main';
						}
						else{
							checkShow=false;
						}
						if(lib.skill[name].textAnimation){
							checkShow=false;
						}
						this.$skill(lib.skill[name].animationStr||lib.translate[name],lib.skill[name].skillAnimation,lib.skill[name].animationColor,checkShow);
						return;
					}
					var player=this;
					game.broadcast(function(player,name,popname){
						player.trySkillAnimate(name,popname);
					},player,name,popname);
					if(lib.animate.skill[name]) lib.animate.skill[name].apply(this,arguments);
					else{
						if(popname!=name) this.popup(popname,'water',false);
						else this.popup(get.skillTranslation(name,this),'water',false);
					}
				},
				tryCardAnimate:function(card,name,nature,popname){
					var player=this;
					game.broadcast(function(player,card,name,nature,popname){
						player.tryCardAnimate(card,name,nature,popname);
					},player,card,name,nature,popname);
					if(lib.animate.card[card.name]) lib.animate.card[card.name].apply(this,arguments);
					else {
						if(!lib.config.show_card_prompt) return;
						if(get.type(card)=='equip'&&lib.config.hide_card_prompt_equip) return;
						if(get.type(card)=='basic'&&lib.config.hide_card_prompt_basic) return;
						if(popname) player.popup({name:card.name,nature:card.nature},nature,false);
						else player.popup(name,nature,false);
					}
				},
				hasUsableCard:function(name){
					var player=this;
					if(player.countCards('hs',name)) return true;
					var skills=player.getSkills('invisible').concat(lib.skill.global);
					game.expandSkills(skills);
					for(var i=0;i<skills.length;i++){
						var ifo=get.info(skills[i]);
						if(ifo.viewAs&&typeof ifo.viewAs!='function'&&ifo.viewAs.name==name){
							if(!ifo.viewAsFilter||ifo.viewAsFilter(player)!==false){
								return true;
							}
						}
						else{
							var hiddenCard=get.info(skills[i]).hiddenCard;
							if(typeof hiddenCard=='function'&&hiddenCard(player,name)){
								return true;
							}
						}
					}
				},
				inRange:function(to){
					var from=this;
					if(from==to||from.hasSkill('undist')||to.hasSkill('undist')) return false;
					if(!game.players.contains(from)&&!game.dead.contains(from)) return false;
					if(!game.players.contains(to)&&!game.dead.contains(to)) return false;
					var mod1=game.checkMod(from,to,'unchanged','inRange',from);
					if(mod1!='unchanged') return mod1;
					var mod2=game.checkMod(from,to,'unchanged','inRangeOf',to);
					if(mod2!='unchanged') return mod2;
					var range=from.getAttackRange();
					if(range<1) return false;
					var player=from,m,n=1,i;
					var fxy,txy;
					if(game.chess){
						fxy=from.getXY();
						txy=to.getXY();
						n=Math.abs(fxy[0]-txy[0])+Math.abs(fxy[1]-txy[1]);
					}
					else if(to.isMin(true)||from.isMin(true)){}
					else{
						var length=game.players.length;
						var totalPopulation=game.players.length+game.dead.length+1;
						for(var iwhile=0;iwhile<totalPopulation;iwhile++){
							if(player.nextSeat!=to){
								player=player.nextSeat;
								if(player.isAlive()&&!player.isOut()&&!player.hasSkill('undist')&&!player.isMin(true)) n++;
							}
							else{
								break;
							}
						}
						for(i=0;i<game.players.length;i++){
							if(game.players[i].isOut()||game.players[i].hasSkill('undist')||game.players[i].isMin(true)) length--;
						}
						if(from.isDead()) length++;
						if(to.isDead()) length++;
						var left=from.hasSkillTag('left_hand');
						var right=from.hasSkillTag('right_hand');
						if(left===right) n=Math.min(n,length-n);
						else if(left==true) n=length-n;
					}
					n=game.checkMod(from,to,n,'globalFrom',from);
					n=game.checkMod(from,to,n,'globalTo',to);
					m=n;
					m=game.checkMod(from,to,m,'attackFrom',from);
					m=game.checkMod(from,to,m,'attackTo',to);
					var equips1=from.getCards('e',function(card){
						return !ui.selected.cards||!ui.selected.cards.contains(card);
					}),equips2=to.getCards('e',function(card){
						return !ui.selected.cards||!ui.selected.cards.contains(card);
					});
					for(i=0;i<equips1.length;i++){
						var info=get.info(equips1[i]).distance;
						if(!info) continue;
						if(info.globalFrom){
							m+=info.globalFrom;
							n+=info.globalFrom;
						}
					}
					for(i=0;i<equips2.length;i++){
						var info=get.info(equips2[i]).distance;
						if(!info) continue;
						if(info.globalTo){
							m+=info.globalTo;
							n+=info.globalTo;
						}
						if(info.attaclTo){
							m+=info.attaclTo;
						}
					}
					return m<=range;
				},
				inRangeOf:function(source){
					return source.inRange(this);
				},
				//Get the player's HP not less than 0. Set “raw” to true to get the player's raw HP instead.
				//获取角色的体力值。设置“raw”为true以获取角色的体力。
				getHp:function(raw){
					return raw?this.hp:Math.max(0,this.hp);
				},
				//Set “raw” to true to get the player's raw damaged HP instead.
				//设置“raw”为true以获取角色已损失的体力。
				getDamagedHp:function(raw){
					return this.maxHp-this.getHp(raw);
				},
				changeGroup:function(group,log,broadcast){
					var next=game.createEvent('changeGroup');
					next.player=this;
					next.log=true;
					for(var i=0;i<arguments.length;i++){
						var arg=arguments[i];
						if(lib.group.contains(arg)){
							next.group=arg;
						}
						else if(typeof arg==='boolean'){
							next.log=arg;
						}
						else if(arg==='nobroadcast'){
							next.broadcast=false;
						}
					}
					next.setContent('changeGroup');
					return next;
				},
				chooseToDuiben:function(target){
					var next=game.createEvent('chooseToDuiben');
					next.player=this;
					next.target=target;
					next.setContent('chooseToDuiben');
					return next;
				},
				chooseToPSS:function(target){
					var next=game.createEvent('chooseToPSS');
					next.player=this;
					next.target=target;
					next.setContent('chooseToPSS');
					return next;
				},
				chooseToEnable:function(){
					var next=game.createEvent('chooseToEnable');
					next.player=this;
					next.setContent('chooseToEnable');
					return next;
				},
				chooseToDisable:function(horse){
					var next=game.createEvent('chooseToDisable');
					next.player=this;
					if(horse) next.horse=true;
					next.setContent('chooseToDisable');
					return next;
				},
				isPhaseUsing:function(notmeisok){
					if(!notmeisok&&_status.currentPhase!=this) return false;
					return _status.event.name=='phaseUse'||_status.event.getParent('phaseUse').name=='phaseUse';
				},
				swapEquip:function(target){
					var next=game.createEvent('swapEquip');
					next.player=this;
					next.target=target;
					next.setContent('swapEquip');
					return next;
				},
				canCompare:function(target){
					if(this==target) return false;
					if(!this.countCards('h')||!target.countCards('h')) return false;
					if(this.hasSkillTag('noCompareSource')||target.hasSkillTag('noCompareTarget')) return false;
					return true;
				},
				$disableJudge:function(){
					var player=this;
					game.addVideo('$disableJudge',player);
					player.storage._disableJudge=true;
					var card=game.createCard('disable_judge','','');
					card.fix();
					card.classList.add('feichu');
					card.style.transform='';
					card.classList.add('drawinghidden');
					player.node.judges.insertBefore(card,player.node.judges.firstChild);
					ui.updatej(player);
				},
				$enableJudge:function(){
					var player=this;
					game.addVideo('$enableJudge',player);
					player.storage._disableJudge=false;
					for(var i=0;i<player.node.judges.childNodes.length;i++){
						if(player.node.judges.childNodes[i].name=='disable_judge'){
							player.node.judges.removeChild(player.node.judges.childNodes[i]);
							break;
						}
					}
				},
				disableJudge:function(){
					var next=game.createEvent('disableJudge');
					next.player=this;
					next.source=_status.event.player;
					next.setContent('disableJudge');
					return next;
				},
				enableJudge:function(){
					var next=game.createEvent('enableJudge');
					next.player=this;
					next.source=_status.event.player;
					next.setContent('enableJudge');
					return next;
				},
				//原有函数
				init:function(character,character2,skill,update){
					if(typeof character=='string'&&!lib.character[character]){
						lib.character[character]=get.character(character);
					}
					if(typeof character2=='string'&&!lib.character[character2]){
						lib.character[character2]=get.character(character2);
					}
					if(!lib.character[character]) return;
					if(get.is.jun(character2)){
						var tmp=character;
						character=character2;
						character2=tmp;
					}
					if(character2==false){
						skill=false;
						character2=null;
					}
					var info=lib.character[character];
					if(!info){
						info=['','',1,[],[]];
					}
					if(!info[4]){
						info[4]=[];
					}
					var skills=info[3].slice(0);
					this.clearSkills(true);
					this.classList.add('fullskin');
					if(!game.minskin&&get.is.newLayout()&&!info[4].contains('minskin')){
						this.classList.remove('minskin');
						this.node.avatar.setBackground(character,'character');
					}
					else{
						this.node.avatar.setBackground(character,'character');
						if(info[4].contains('minskin')){
							this.classList.add('minskin');
						}
						else if(game.minskin){
							this.classList.add('minskin');
						}
						else{
							this.classList.remove('minskin');
						}
					}

					var hp1=get.infoHp(info[2]);
					var maxHp1=get.infoMaxHp(info[2]);
					var hujia1=get.infoHujia(info[2]);
					
					this.node.avatar.show();
					this.node.count.show();
					this.node.equips.show();
					this.name=character;
					this.name1=character;
					this.sex=info[0];
					this.group=info[1];
					this.hp=hp1;
					this.maxHp=maxHp1;
					this.hujia=hujia1;
					this.node.intro.innerHTML=lib.config.intro;
					this.node.name.dataset.nature=get.groupnature(this.group);
					lib.setIntro(this);
					this.node.name.innerHTML=get.slimName(character);
					if(this.classList.contains('minskin')&&this.node.name.querySelectorAll('br').length>=4){
						this.node.name.classList.add('long');
					}
					if(info[4].contains('hiddenSkill')&&!this.noclick){
						if(!this.hiddenSkills) this.hiddenSkills=[];
						this.hiddenSkills.addArray(skills);
						skills=[];
						this.classList.add(_status.video?'unseen_v':'unseen');
						this.name='unknown';
						if(!this.node.name_seat&&!_status.video){
							this.node.name_seat=ui.create.div('.name.name_seat',get.verticalStr(get.translation(this.name)),this);
							this.node.name_seat.dataset.nature=get.groupnature(this.group);
						}
						this.sex='male';
						//this.group='unknown';
						this.storage.nohp=true;
						skills.add('g_hidden_ai');
					}
					if(character2&&lib.character[character2]){
						var info2=lib.character[character2];
						if(!info2){
							info2=['','',1,[],[]];
						}
						if(!info2[4]){
							info2[4]=[];
						}
						this.classList.add('fullskin2');
						this.node.avatar2.setBackground(character2,'character');

						this.node.avatar2.show();
						this.name2=character2;
						var hp2=get.infoHp(info2[2]);
						var maxHp2=get.infoMaxHp(info2[2]);
						var hujia2=get.infoHujia(info2[2]);
						this.hujia+=hujia2;
						var double_hp;
						if(_status.connectMode||get.mode()=='single'){
							double_hp='pingjun';
						}
						else{
							double_hp=get.config('double_hp');
						}
						switch(double_hp){
							case 'pingjun':{
								this.maxHp=Math.floor((maxHp1+maxHp2)/2);
								this.hp=Math.floor((hp1+hp2)/2);
								this.singleHp=((maxHp1+maxHp2)%2===1);
								break;
							}
							case 'zuidazhi':{
								this.maxHp=Math.max(maxHp1,maxHp2);
								this.hp=Math.max(hp1,hp2);
								break;
							}
							case 'zuixiaozhi':{
								this.maxHp=Math.min(maxHp1,maxHp2);
								this.hp=Math.min(hp1,hp2);
								break;
							}
							case 'zonghe':{
								this.maxHp=maxHp1+maxHp2;
								this.hp=hp1+hp2;
								break;
							}
							default:{
								this.maxHp=maxHp1+maxHp2-3;
								this.hp=hp1+hp2-3;
							};
						}
						this.node.count.classList.add('p2');
						if(info2[4].contains('hiddenSkill')&&!this.noclick){
							if(!this.hiddenSkills) this.hiddenSkills=[];
							this.hiddenSkills.addArray(info2[3]);
							this.classList.add(_status.video?'unseen2_v':'unseen2');
							this.storage.nohp=true;
							skills.add('g_hidden_ai');
						}
						else skills=skills.concat(info2[3]);

						this.node.name2.innerHTML=get.slimName(character2);
					}
					if(this.storage.nohp){
						this.storage.rawHp=this.hp;
						this.storage.rawMaxHp=this.maxHp;
						this.hp=1;
						this.maxHp=1;
						this.node.hp.hide();
					}
					if(skill!=false){
						skills=skills.filter(skill=>{
							var info=get.info(skill);
							if(info&&info.zhuSkill&&!this.isZhu2()) return false;
							return true;
						});
						for(var i=0;i<skills.length;i++){
							this.addSkill(skills[i],null,true);
						}
						this.checkConflict();
					}
					lib.group.add(this.group);
					if(this.inits){
						for(var i=0;i<lib.element.player.inits.length;i++){
							lib.element.player.inits[i](this);
						}
					}
					if(this._inits){
						for(var i=0;i<this._inits.length;i++){
							this._inits[i](this);
						}
					}
					if(update!==false) this.$update();
					return this;
				},
				initOL:function(name,character){
					this.node.avatar.setBackground(character,'character');
					this.node.avatar.show();
					this.node.name.innerHTML=get.verticalStr(name);
					this.nickname=name;
					this.avatar=character;
					this.node.nameol.innerHTML='';
					if(lib.character[character]) this.sex=lib.character[character][0];
				},
				uninitOL:function(){
					this.node.avatar.hide();
					this.node.name.innerHTML='';
					this.node.identity.firstChild.innerHTML='';
					delete this.nickname;
					delete this.avatar;
					delete this.sex;
				},
				initRoom:function(info,info2){
					var str='';
					this.serving=false;
					if(!info||info=='server'){
						this.roomempty=true;
						str='空房间';
						this.roomfull=false;
						this.roomgaming=false;
						this.version=null;
						if(info=='server'){
							this.serving=true;
						}
					}
					else{
						var config=info[2];
						this.key=info[4];
						this.roomempty=false;
						str+=get.modetrans(config);
						str+=' 模式 ';
						for(var i=str.length;i<11;i++) str+=' ';
						this.version=config.version;
						if(config.gameStarted){
							str+='<span class="firetext">游戏中</span> ';
							if(config.observe&&config.observeReady&&this.version==lib.versionOL){
								this.classList.remove('exclude');
							}
							else{
								this.classList.add('exclude');
							}
						}
						else{
							str+='<span class="greentext">等待中</span> ';
							if(this.version!=lib.versionOL){
								this.classList.add('exclude');
							}
							else{
								this.classList.remove('exclude');
							}
						}
						this.maxHp=parseInt(config.number);
						this.hp=Math.min(this.maxHp,info[3]);
						if(this.hp<this.maxHp||config.gameStarted) str+=('人数:'+this.hp+'/'+this.maxHp);
						else str+=('人数:<span class="firetext">'+this.hp+'/'+this.maxHp+'</span>');
						
						str+=(' ('+info[0].slice(0,12)+' 的房间)');
						if(config.mode!='guozhan'&&(config.mode!='doudizhu'||config.doudizhu_mode!='online')){
							str+='【';
							for(var i=0;i<config.cardPack.length;i++){
								str+=(get.translation(config.cardPack[i]+'_card_config').slice(0,2));
								if(i<config.cardPack.length-1) str+='+';
							}
							str+='】';
						}
						this.config=config;
						if(this.hp==this.maxHp&&!config.gameStarted){
							this.roomfull=true;
						}
						else{
							this.roomfull=false;
						}
						if(config.gameStarted&&(!config.observe||!config.observeReady)){
							this.roomgaming=true;
						}
						else{
							this.roomgaming=false;
						}
					}
					this.firstChild.innerHTML=str;
					return this;
				},
				reinit:function(from,to,maxHp,online){
					var info1=lib.character[from];
					var info2=lib.character[to];
					var smooth=true;
					if(maxHp=='nosmooth'){
						smooth=false;
						maxHp=null;
					}
					if(this.name2==from){
						this.name2=to;
						if(this.isUnseen(0)&&!this.isUnseen(1)){
							this.sex=info2[0];
							this.name=to;
						}
						if(smooth) this.smoothAvatar(true);
						this.node.avatar2.setBackground(to,'character');
						this.node.name2.innerHTML=get.slimName(to);
					}
					else if(this.name==from||this.name1==from){
						if(this.name1==from){
							this.name1=to;
						}
						if(!this.classList.contains('unseen2')){
							this.name=to;
							this.sex=info2[0];
						}
						if(smooth) this.smoothAvatar(false);
						this.node.avatar.setBackground(to,'character');
						this.node.name.innerHTML=get.slimName(to);

						if(this==game.me&&ui.fakeme){
							ui.fakeme.style.backgroundImage=this.node.avatar.style.backgroundImage;
						}
					}
					else{
						return this;
					}
					if(online){
						return;
					}
					for(var i=0;i<info1[3].length;i++){
						this.removeSkill(info1[3][i]);
					}
					for(var i=0;i<info2[3].length;i++){
						var info=get.info(info2[3][i]);
						if(info&&info.zhuSkill&&!this.isZhu2()) continue;
						this.addSkill(info2[3][i]);
					}
					if(Array.isArray(maxHp)){
						this.maxHp=maxHp[1];
						this.hp=maxHp[0];
					}
					else{
						var num;
						if(maxHp===false){
							num=0;
						}
						else{
							if(typeof maxHp!='number'){
								maxHp=get.infoMaxHp(info2[2]);
							}
							num=maxHp-get.infoMaxHp(info1[2]);
						}
						if(typeof this.singleHp=='boolean'){
							if(num%2!=0){
								if(this.singleHp){
									this.maxHp+=(num+1)/2;
									this.singleHp=false;
								}
								else{
									this.maxHp+=(num-1)/2;
									this.singleHp=true;
									if(!game.online){
										this.doubleDraw();
									}
								}
							}
							else{
								this.maxHp+=num/2;
							}
						}
						else{
							this.maxHp+=num;
						}
					}
					game.broadcast(function(player,from,to,skills){
						player.reinit(from,to,null,true);
						player.applySkills(skills);
					},this,from,to,get.skillState(this));
					game.addVideo('reinit3',this,{
						from:from,
						to:to,
						hp:this.maxHp,
						avatar2:this.name2==to
					});
					this.update();
				},
				uninit:function(){
					this.expandedSlots={};
					this.disabledSlots={};
					this.$syncDisable();
					if(this.isDisabledJudge()){
						game.broadcastAll(function(player){
							player.storage._disableJudge=false;
							for(var i=0;i<player.node.judges.childNodes.length;i++){
								if(player.node.judges.childNodes[i].name=='disable_judge'){
									player.node.judges.removeChild(player.node.judges.childNodes[i]);
									break;
								}
							}
						},this);
					}
					this.node.avatar.hide();
					this.node.count.hide();
					if(this.node.wuxing){
						this.node.wuxing.hide();
					}
					if(this.node.name_seat){
						this.node.name_seat.remove();
						delete this.node.name_seat;
					}
					if(this.storage.nohp) this.node.hp.show();
					this.classList.remove('unseen');
					this.classList.remove('unseen2');
					delete this.name;
					delete this.name1;
					delete this.sex;
					delete this.group;
					delete this.hp;
					delete this.maxHp;
					delete this.hujia;
					this.clearSkills(true);
					this.node.identity.style.backgroundColor='';
					this.node.intro.innerHTML='';
					this.node.name.innerHTML='';
					this.node.hp.innerHTML='';
					this.node.count.innerHTML='0';
					if(this.name2){
						delete this.singleHp;
						this.node.avatar2.hide();
						this.node.name2.innerHTML='';
						this.classList.remove('fullskin2')
						delete this.name2;
						this.node.count.classList.remove('p2');
					}
					for(var mark in this.marks){
						this.marks[mark].remove();
					}
					ui.updatem(this);

					this.skipList=[];
					this.skills=this.skills.contains('cangji_yozuru')?['cangji_yozuru']:[];
					this.initedSkills=[];
					this.additionalSkills={};
					this.disabledSkills={};
					this.hiddenSkills=[];
					this.awakenedSkills=[];
					this.forbiddenSkills={};
					this.phaseNumber=0;
					this.stat=[{card:{},skill:{}}];
					this.tempSkills={};
					this.storage={};
					this.marks={};
					this.ai={friend:[],enemy:[],neutral:[]};

					return this;
				},
				getLeft:function(){
					return this.offsetLeft;
				},
				getTop:function(){
					return this.offsetTop;
				},
				smoothAvatar:function(vice,video){
					var div=ui.create.div('.fullsize');
					if(vice){
						div.style.background=getComputedStyle(this.node.avatar2).background;
						this.node.avatar2.appendChild(div);
					}
					else{
						div.style.background=getComputedStyle(this.node.avatar).background;
						this.node.avatar.appendChild(div);
					}
					ui.refresh(div);
					div.style.transition='all 1s';
					setTimeout(function(){
						div.classList.add('removing');
						setTimeout(function(){
							div.remove();
						},2000);
					},100);
					if(video!=false){
						game.addVideo('smoothAvatar',this,vice);
					}
				},
				changeSeat:function(position,video){
					var player=this;
					if(video!==false) game.addVideo('changeSeat',player,position);
					var rect1=player.getBoundingClientRect();
					player.style.transition='all 0s';
					ui.refresh(player);
					player.dataset.position=position;
					var rect2=player.getBoundingClientRect();
					var dx=rect1.left-rect2.left;
					var dy=rect1.top-rect2.top;
					if((game.chess||(player.dataset.position!=0&&position!=0))&&player.classList.contains('linked')){
						player.style.transform='rotate(-90deg) translate('+(-dy)+'px,'+(dx)+'px)';
					}
					else{
						player.style.transform='translate('+(dx)+'px,'+(dy)+'px)';
					}
					setTimeout(function(){
						player.style.transition='';
						ui.refresh(player);
						player.style.transform='';
					},100);
				},
				send:function(){
					if(!this.ws||this.ws.closed) return this;
					this.ws.send.apply(this.ws,arguments);
					return this;
				},
				getId:function(){
					if(_status.video||_status.connectMode) return this;
					if(this.playerid){
						delete game.playerMap[this.playerid];
					}
					this.playerid=get.id();
					game.playerMap[this.playerid]=this;
					return this;
				},
				throwEmotion:function(target,emotion){
					game.broadcastAll(function(player,target,emotion){
						player.$throwEmotion(target,emotion);
					},this,target,emotion);
				},
				emotion:function(pack,id){
					var str='<img src="##assetURL##image/emotion/'+pack+'/'+id+'.gif" width="50" height="50">';
					lib.element.player.say.call(this,str);
					game.broadcast(function(id,str){
						if(lib.playerOL[id]){
							lib.playerOL[id].say(str);
						}
						else if(game.connectPlayers){
							for(var i=0;i<game.connectPlayers.length;i++){
								if(game.connectPlayers[i].playerid==id){
									lib.element.player.say.call(game.connectPlayers[i],str);
									return;
								}
							}
						}
					},this.playerid,str);
				},
				chat:function(str){
					if(get.is.banWords(str)) return;
					lib.element.player.say.call(this,str);
					game.broadcast(function(id,str){
						if(lib.playerOL[id]){
							lib.playerOL[id].say(str);
						}
						else if(game.connectPlayers){
							for(var i=0;i<game.connectPlayers.length;i++){
								if(game.connectPlayers[i].playerid==id){
									lib.element.player.say.call(game.connectPlayers[i],str);
									return;
								}
							}
						}
					},this.playerid,str);
				},
				say:function(str){
					str=str.replace(/##assetURL##/g,lib.assetURL);
					var dialog=ui.create.dialog('hidden');
					dialog.classList.add('static');
					dialog.add('<div class="text" style="word-break:break-all;display:inline">'+str+'</div>');
					dialog.classList.add('popped');
					ui.window.appendChild(dialog);
					var width=dialog.content.firstChild.firstChild.offsetWidth;
					if(width<190){
						dialog._mod_height=-16;
					}
					else{
						dialog.content.firstChild.style.textAlign='left';
					}
					dialog.style.width=(width+16)+'px';
					var refnode;
					if(this.node&&this.node.avatar&&this.parentNode==ui.arena){
						refnode=this.node.avatar;
					}
					if(refnode){
						lib.placePoppedDialog(dialog,{
							clientX:(ui.arena.offsetLeft+this.getLeft()+refnode.offsetLeft+refnode.offsetWidth/2)*game.documentZoom,
							clientY:(ui.arena.offsetTop+this.getTop()+refnode.offsetTop+refnode.offsetHeight/4)*game.documentZoom
						});
					}
					else{
						lib.placePoppedDialog(dialog,{
							clientX:(this.getLeft()+this.offsetWidth/2)*game.documentZoom,
							clientY:(this.getTop()+this.offsetHeight/4)*game.documentZoom
						});
					}
					if(dialog._mod_height){
						dialog.content.firstChild.style.padding=0;
					}
					setTimeout(function(){
						dialog.delete();
					},lib.quickVoice.includes(str)?3800:2000);
					var name=get.translation(this.name);
					var info=[name?(name+'['+this.nickname+']'):this.nickname,str];
					lib.chatHistory.push(info);
					if(_status.addChatEntry){
						if(_status.addChatEntry._origin.parentNode){
							_status.addChatEntry(info,false);
						}
						else{
							delete _status.addChatEntry;
						}
					}
					if(lib.config.background_speak&&lib.quickVoice.includes(str)){
						game.playAudio('voice',(this.sex=='female'?'female':'male'),lib.quickVoice.indexOf(str));
					}
				},
				showGiveup:function(){
					this._giveUp=true;
					if(this==game.me){
						ui.create.giveup();
					}
					else if(this.isOnline2()){
						this.send(ui.create.giveup);
					}
				},
				applySkills:function(skills){
					for(var i in skills){
						if(i=='global'){
							lib.skill.global=skills[i];
						}
						//else if(i=='skillinfo'){
						//	for(var j in skills[i]){
						//		if(!lib.skill[j]){
						//			lib.skill[j]={};
						//		}
						//		lib.skill[j].chooseButton=skills[i][j];
						//	}
						//}
						else if(i=='stat'){
							this.stat=[skills.stat];
						}
						else if(lib.playerOL[i]){
							for(var j in skills[i]){
								lib.playerOL[i][j]=skills[i][j];
							}
						}
					}
				},
				getState:function(){
					var state={
						hp:this.hp,
						maxHp:this.maxHp,
						nickname:this.nickname,
						sex:this.sex,
						group:this.group,
						name:this.name,
						name1:this.name1,
						name2:this.name2,
						handcards:this.getCards('hs'),
						gaintag:[],
						equips:this.getCards('e'),
						judges:this.getCards('j'),
						specials:this.getCards('s'),
						expansions:this.getCards('x'),
						expansion_gaintag:[],
						disableJudge:this.isDisabledJudge(),
						disabledSlots:this.disabledSlots,
						expandedSlots:this.expandedSlots,
						views:[],
						position:parseInt(this.dataset.position),
						hujia:this.hujia,
						side:this.side,
						identityShown:this.identityShown,
						identityNode:[this.node.identity.innerHTML,this.node.identity.dataset.color],
						identity:this.identity,
						dead:this.isDead(),
						linked:this.isLinked(),
						turnedover:this.isTurnedOver(),
						out:this.isOut(),
						phaseNumber:this.phaseNumber,
						unseen:this.isUnseen(0),
						unseen2:this.isUnseen(1),
						seatNum:this.seatNum,
					}
					for(var i=0;i<state.judges.length;i++){
						state.views[i]=state.judges[i].viewAs;
					}
					for(var i=0;i<state.handcards.length;i++){
						state.gaintag[i]=state.handcards[i].gaintag;
					}
					for(var i=0;i<state.expansions.length;i++){
						state.expansion_gaintag[i]=state.expansions[i].gaintag;
					}
					if(this.getModeState){
						state.mode=this.getModeState();
					}
					return state;
				},
				setNickname:function(str){
					this.node.nameol.innerHTML=(str||this.nickname||'').slice(0,12);
					return this;
				},
				setAvatar:function(name,name2,video,fakeme){
					var node;
					if(this.name2==name){
						node=this.node.avatar2;
						this.smoothAvatar(true,video);
					}
					else if(this.name==name){
						node=this.node.avatar;
						this.smoothAvatar(false,video);
					}
					if(node){
						node.setBackground(name2,'character');
						if(this==game.me&&ui.fakeme&&fakeme!==false){
							ui.fakeme.style.backgroundImage=node.style.backgroundImage;
						}
						if(video!=false){
							game.addVideo('setAvatar',this,[name,name2]);
						}
					}
					game.broadcast(function(player,name,name2){
						player.setAvatar(name,name2,false);
					},this,name,name2);
				},
				setAvatarQueue:function(name, list){
					var node;
					var player=this;
					if(player.name2==name){
						node=player.node.avatar2;
					}
					else{
						node=player.node.avatar;
					}
					if(node._avatarqueue){
						for(var i=0;i<list.length;i++){
							node._avatarqueue.push(list[i]);
						}
					}
					else{
						var func=function(){
							if(node._avatarqueue.length){
								player.setAvatar(name,node._avatarqueue.shift(),false,false);
							}
							else{
								clearInterval(node._avatarqueueinterval);
								delete node._avatarqueue;
								delete node._avatarqueueinterval;
								player.setAvatar(name,name,false,false);
							}
						};
						node._avatarqueue=list.slice(0);
						node._avatarqueueinterval=setInterval(func,1000);
						func();
					}
					game.addVideo('setAvatarQueue',this,[name,list]);
				},
				flashAvatar:function(skill,name){
					if(lib.skill[name]&&!lib.character[name]){
						var stop=false;
						var list=lib.config.all.characters.slice(0);
						for(var i in lib.characterPack){
							list.add(i);
						}
						for(var i=0;i<list.length;i++){
							for(var j in lib.characterPack[list[i]]){
								if(lib.characterPack[list[i]][j][3].contains(name)){
									name=j;
									stop=true;
									break;
								}
							}
							if(stop){
								break;
							}
						}
					}
					if(lib.character[this.name2]&&lib.character[this.name2][3].contains(skill)){
						this.setAvatarQueue(this.name2,[name]);
					}
					else{
						this.setAvatarQueue(this.name,[name]);
					}
				},
				update:function(){
					if(_status.video&&arguments.length==0) return;
					if(this.hp>=this.maxHp) this.hp=this.maxHp;
					game.broadcast(function(player,hp,maxHp,hujia){
						player.hp=hp;
						player.maxHp=maxHp;
						player.hujia=hujia;
						player.$update();
					},this,this.hp,this.maxHp,this.hujia);
					this.$update();
				},
				$update:function(){
					if(this.hp>=this.maxHp) this.hp=this.maxHp;
					var hp=this.node.hp;
					hp.style.transition='none';
					if(!_status.video){
						if(this.hujia){
							this.markSkill('ghujia');
						}
						else{
							this.unmarkSkill('ghujia');
						}
					}
					if(!this.storage.nohp){
						if(this.maxHp==Infinity){
							hp.innerHTML='∞';
						}
						else if(game.layout=='default'&&this.maxHp>14){
							hp.innerHTML=this.hp+'/'+this.maxHp;
							hp.classList.add('text');
						}
						else if(get.is.newLayout()&&
						(
							this.maxHp>9||
							(this.maxHp>5&&this.classList.contains('minskin'))||
							((game.layout=='mobile'||game.layout=='long')&&this.dataset.position==0&&this.maxHp>7)
						)){
							hp.innerHTML=this.hp+'<br>/<br>'+this.maxHp+'<div></div>';
							if(this.hp==0){
								hp.lastChild.classList.add('lost');
							}
							hp.classList.add('textstyle');
							// hp.classList.remove('long');
						}
						else{
							hp.innerHTML='';
							hp.classList.remove('text');
							hp.classList.remove('textstyle');
							while(this.maxHp>hp.childNodes.length){
								ui.create.div(hp);
							}
							while(Math.max(0,this.maxHp)<hp.childNodes.length){
								hp.removeChild(hp.lastChild);
							}
							for(var i=0;i<this.maxHp;i++){
								var index=i;
								if(get.is.newLayout()){
									index=this.maxHp-i-1;
								}
								if(i<this.hp){
									hp.childNodes[index].classList.remove('lost');
								}
								else{
									hp.childNodes[index].classList.add('lost');
								}
							}
							// if(this.maxHp==9){
							// 	hp.classList.add('long');
							// }
							// else{
							// 	hp.classList.remove('long');
							// }
						}
						if(hp.classList.contains('room')){
							hp.dataset.condition='high';
						}
						else if(this.hp==0){
							hp.dataset.condition='';
						}
						else if(this.hp>Math.round(this.maxHp/2)||this.hp===this.maxHp){
							hp.dataset.condition='high';
						}
						else if(this.hp>Math.floor(this.maxHp/3)){
							hp.dataset.condition='mid';
						}
						else{
							hp.dataset.condition='low';
						}
	
						setTimeout(function(){
							hp.style.transition='';
						});
					}
					var numh=this.countCards('h');
					if(_status.video){
						numh=arguments[0];
					}
					if(numh>=10){
						numh=numh.toString();
						this.node.count.dataset.condition='low';
						this.node.count.innerHTML=numh[0]+'<br>'+numh[1];
					}
					else{
						if(numh>5){
							this.node.count.dataset.condition='higher';
						}
						else if(numh>2){
							this.node.count.dataset.condition='high';
						}
						else if(numh>0){
							this.node.count.dataset.condition='mid';
						}
						else{
							this.node.count.dataset.condition='none';
						}
						this.node.count.innerHTML=numh;
					}
					if(this.updates){
						for(var i=0;i<lib.element.player.updates.length;i++){
							lib.element.player.updates[i](this);
						}
					}
					if(!_status.video){
						game.addVideo('update',this,[this.countCards('h'),this.hp,this.maxHp,this.hujia]);
					}
					this.updateMarks();
					return this;
				},
				clearMark:function(i,log){
					let num=this.countMark(i);
					if(num>0) this.removeMark(i,num,log)
				},
				removeMark:function(i,num,log){
					if(typeof num!='number'||!num) num=1;
					if(typeof this.storage[i]!='number'||!this.storage[i]) return;
					if(num>this.storage[i]) num=this.storage[i];
					this.storage[i]-=num;
					if(log!==false){
						var str=false;
						var info=get.info(i);
						if(info&&info.intro&&(info.intro.name||info.intro.name2)) str=info.intro.name2||info.intro.name;
						else str=lib.translate[i];
						if(str) game.log(this,'移去了',get.cnNumber(num),'个','#g【'+str+'】');
					}
					this.syncStorage(i);
					this[(this.storage[i]||(lib.skill[i]&&lib.skill[i].mark))?'markSkill':'unmarkSkill'](i);
				},
				addMark:function(i,num,log){
					if(typeof num!='number'||!num) num=1;
					if(typeof this.storage[i]!='number') this.storage[i]=0;
					this.storage[i]+=num;
					if(log!==false){
						var str=false;
						var info=get.info(i);
						if(info&&info.intro&&(info.intro.name||info.intro.name2)) str=info.intro.name2||info.intro.name;
						else str=lib.translate[i];
						if(str) game.log(this,'获得了',get.cnNumber(num),'个','#g【'+str+'】');
					}
					this.syncStorage(i);
					this.markSkill(i);
				},
				setMark:function(name,num,log){
					const count=this.countMark(name);
					if(count>num)this.removeMark(name,count-num,log);
					else if(count<num)this.addMark(name,num-count,log);
				},
				countMark:function(i){
					if(this.storage[i]==undefined) return 0;
					if(typeof this.storage[i]=='number') return this.storage[i];
					if(Array.isArray(this.storage[i])) return this.storage[i].length;
					return 0;
				},
				hasMark:function(i){
					return this.countMark(i)>0;
				},
				updateMark:function(i,storage){
					if(!this.marks[i]){
						if(lib.skill[i]&&lib.skill[i].intro&&(this.storage[i]||lib.skill[i].intro.markcount)){
							this.markSkill(i);
							if(!this.marks[i]) return this;
						}
						else{
							return this;
						}
					}
					if(storage&&this.storage[i]){
						this.syncStorage(i);
					}
					if(i=='ghujia'||((!this.marks[i].querySelector('.image')||this.storage[i+'_markcount'])&&
						lib.skill[i]&&lib.skill[i].intro&&!lib.skill[i].intro.nocount&&
						(this.storage[i]||this.storage[i+'_markcount']||lib.skill[i].intro.markcount))){
						this.marks[i].classList.add('overflowmark')
						var num=0;
						if(typeof lib.skill[i].intro.markcount=='function'){
							num=lib.skill[i].intro.markcount(this.storage[i],this);
						}
						else if(lib.skill[i].intro.markcount=='expansion'){
							num=this.countCards('x',(card)=>card.hasGaintag(i));
						}
						else if(typeof this.storage[i+'_markcount']=='number'){
							num=this.storage[i+'_markcount'];
						}
						else if(i=='ghujia'){
							num=this.hujia;
						}
						else if(typeof this.storage[i]=='number'){
							num=this.storage[i];
						}
						else if(Array.isArray(this.storage[i])){
							num=this.storage[i].length;
						}
						if(num){
							if(!this.marks[i].markcount){
								this.marks[i].markcount=ui.create.div('.markcount.menubutton',this.marks[i]);
							}
							this.marks[i].markcount.innerHTML=num;
						}
						else if(this.marks[i].markcount){
							this.marks[i].markcount.delete();
							delete this.marks[i].markcount;
						}
					}
					else{
						if(this.marks[i].markcount){
							this.marks[i].markcount.delete();
							delete this.marks[i].markcount;
						}
						if(lib.skill[i].mark=='auto'){
							this.unmarkSkill(i);
						}
					}
					return this;
				},
				updateMarks:function(connect){
					if(typeof connect=='string'&&_status.connectMode&&!game.online){
						game.broadcast(function(player,storage,skill){
							player.storage[skill]=storage;
							player.updateMarks();
						},this,this.storage[connect],connect);
					}
					for(var i in this.marks){
						this.updateMark(i);
					}
				},
				num:function(arg1,arg2,arg3){
					if(get.itemtype(arg1)=='position'){
						return this.get(arg1,arg2,arg3).length;
					}
					else if(arg1=='s'){
						if(typeof arg2=='boolean'){
							return game.expandSkills(this.getSkills(arg2).concat(lib.skill.global)).contains(arg3);
						}
						else{
							return game.expandSkills(this.getSkills().concat(lib.skill.global)).contains(arg2);
						}
					}
				},
				line:function(target,config){
					if(get.itemtype(target)=='players'){
						for(var i=0;i<target.length;i++){
							this.line(target[i],config);
						}
					}
					else if(get.itemtype(target)=='player'){
						if(target==this) return;
						game.broadcast(function(player,target,config){
							player.line(target,config);
						},this,target,config);
						game.addVideo('line',this,[target.dataset.position,config]);
						game.linexy([
							this.getLeft()+this.offsetWidth/2,
							this.getTop()+this.offsetHeight/2,
							target.getLeft()+target.offsetWidth/2,
							target.getTop()+target.offsetHeight/2
						],config,true);
					}
				},
				line2:function(targets,config){
					this.line(targets[0],config);
					targets=targets.slice(0);
					for(var i=1;i<targets.length;i++){
						(function(j){
							setTimeout(function(){
								targets[j-1].line(targets[j],config);
							},lib.config.duration*i);
						}(i));
					}
				},
				getNext:function(){
					if(this.hasSkill('undist')) return null;
					var target=this;
					for(var i=0;i<game.players.length-1;i++){
						target=target.next;
						if(!target.hasSkill('undist')){
							return target;
						}
					}
					return null;
				},
				getPrevious:function(){
					if(this.hasSkill('undist')) return null;
					var target=this;
					for(var i=0;i<game.players.length-1;i++){
						target=target.previous;
						if(!target.hasSkill('undist')){
							return target;
						}
					}
					return null;
				},
				countUsed:function(card,type){
					if(type===true){
						var num=0;
						var history=this.getHistory('useCard');
						for(var i=0;i<history.length;i++){
							if(!card) num++;
							else if(typeof card=='string'&&history[i].card&&card==history[i].card.name) num++;
							else if(typeof card=='object'&&history[i].card&&card.name==history[i].card.name) num++;
						}
						return num;
					}
					var num;
					var stat=this.getStat('card');
					if(!card){
						num=0;
						for(var i in stat){
							if(typeof stat[i]=='number') num+=stat[i];
						}
						return num;
					}
					if(typeof card=='object'){
						card=card.name;
					}
					num=stat[card];
					if(typeof num!='number') return 0;
					return num;
				},
				countSkill:function(skill){
					var num=this.getStat('skill')[skill];
					if(num==undefined) return 0;
					return num;
				},
				getStockSkills:function(unowned,unique,hidden){
					var list=[];
					if(lib.character[this.name]&&(hidden||!this.isUnseen(0))){
						list.addArray(lib.character[this.name][3]);
					}
					if(lib.character[this.name1]&&(hidden||!this.isUnseen(0))){
						list.addArray(lib.character[this.name1][3]);
					}
					if(lib.character[this.name2]&&(hidden||!this.isUnseen(1))){
						list.addArray(lib.character[this.name2][3]);
					}
					if(!unowned){
						for(var i=0;i<list.length;i++){
							if(!this.hasSkill(list[i])){
								list.splice(i--,1);
							}
						}
					}
					if(!unique){
						for(var i=0;i<list.length;i++){
							var info=lib.skill[list[i]];
							if(!info||info.unique||info.temp||info.sub||info.charlotte){
								list.splice(i--,1);
							}
						}
					}
					return list;
				},
				getCards:function(arg1,arg2){
					if(typeof arg1!='string'){
						arg1='h';
					}
					var cards=[],cards1=[];
					var i,j;
					for(i=0;i<arg1.length;i++){
						if(arg1[i]=='h'){
							for(j=0;j<this.node.handcards1.childElementCount;j++){
								if(!this.node.handcards1.childNodes[j].classList.contains('removing')&&!this.node.handcards1.childNodes[j].classList.contains('glows')){
									cards.push(this.node.handcards1.childNodes[j]);
								}
							}
							for(j=0;j<this.node.handcards2.childElementCount;j++){
								if(!this.node.handcards2.childNodes[j].classList.contains('removing')&&!this.node.handcards2.childNodes[j].classList.contains('glows')){
									cards.push(this.node.handcards2.childNodes[j]);
								}
							}
						}
						else if(arg1[i]=='s'){
							for(j=0;j<this.node.handcards1.childElementCount;j++){
								if(!this.node.handcards1.childNodes[j].classList.contains('removing')&&this.node.handcards1.childNodes[j].classList.contains('glows')){
									cards.push(this.node.handcards1.childNodes[j]);
								}
							}
							for(j=0;j<this.node.handcards2.childElementCount;j++){
								if(!this.node.handcards2.childNodes[j].classList.contains('removing')&&this.node.handcards2.childNodes[j].classList.contains('glows')){
									cards.push(this.node.handcards2.childNodes[j]);
								}
							}
						}
						else if(arg1[i]=='e'){
							for(j=0;j<this.node.equips.childElementCount;j++){
								if(!this.node.equips.childNodes[j].classList.contains('removing')&&!this.node.equips.childNodes[j].classList.contains('feichu')){
									cards.push(this.node.equips.childNodes[j]);
								}
							}
						}
						else if(arg1[i]=='j'){
							for(j=0;j<this.node.judges.childElementCount;j++){
								if(!this.node.judges.childNodes[j].classList.contains('removing')&&!this.node.judges.childNodes[j].classList.contains('feichu')){
									cards.push(this.node.judges.childNodes[j]);
									if(this.node.judges.childNodes[j].viewAs&&arguments.length>1){
										this.node.judges.childNodes[j].tempJudge=this.node.judges.childNodes[j].name;
										this.node.judges.childNodes[j].name=this.node.judges.childNodes[j].viewAs;
										cards1.push(this.node.judges.childNodes[j]);
									}
								}
							}
						}
						else if(arg1[i]=='x'){
							for(j=0;j<this.node.expansions.childElementCount;j++){
								if(!this.node.expansions.childNodes[j].classList.contains('removing')){
									cards.push(this.node.expansions.childNodes[j]);
								}
							}
						}
					}
					if(arguments.length==1){
						return cards;
					}
					if(arg2){
						if(typeof arg2=='string'){
							for(i=0;i<cards.length;i++){
								if(get.name(cards[i])!=arg2){
									cards.splice(i,1);i--;
								}
							}
						}
						else if(typeof arg2=='object'){
							for(i=0;i<cards.length;i++){
								for(j in arg2){
									var value;
									if(j=='type'||j=='subtype'||j=='color'||j=='suit'||j=='number'){
										value=get[j](cards[i]);
									}
									else{
										value=cards[i][j];
									}
									if((typeof arg2[j]=='string'&&value!=arg2[j])||
										(Array.isArray(arg2[j])&&!arg2[j].contains(value))){
										cards.splice(i--,1);break;
									}
								}
							}
						}
						else if(typeof arg2=='function'){
							for(i=0;i<cards.length;i++){
								if(!arg2(cards[i])){
									cards.splice(i--,1);
								}
							}
						}
					}
					for(i=0;i<cards1.length;i++){
						if(cards1[i].tempJudge){
							cards1[i].name=cards1[i].tempJudge;
							delete cards1[i].tempJudge;
						}
					}
					return cards;
				},
				getDiscardableCards:function(player,arg1,arg2){
					var cards=this.getCards(arg1,arg2);
					for(var i=0;i<cards.length;i++){
						if(!lib.filter.canBeDiscarded(cards[i],player,this)){
							cards.splice(i--,1);
						}
					}
					return cards;
				},
				getGainableCards:function(player,arg1,arg2){
					var cards=this.getCards(arg1,arg2);
					for(var i=0;i<cards.length;i++){
						if(!lib.filter.canBeGained(cards[i],player,this)){
							cards.splice(i--,1);
						}
					}
					return cards;
				},
				getGainableSkills:function(func){
					var list=[];
					var names=[this.name,this.name1,this.name2];
					for(var i=0;i<names.length;i++){
						list.addArray(get.gainableSkillsName(names[i],func));
					}
					return list;
				},
				countCards:function(arg1,arg2){
					return this.getCards(arg1,arg2).length;
				},
				countDiscardableCards:function(player,arg1,arg2){
					return this.getDiscardableCards(player,arg1,arg2).length;
				},
				countGainableCards:function(player,arg1,arg2){
					return this.getGainableCards(player,arg1,arg2).length;
				},
				getOriginalSkills:function(){
					var skills=[];
					if(lib.character[this.name]&&!this.isUnseen(0)){
						skills.addArray(lib.character[this.name][3]);
					}
					if(this.name2&&lib.character[this.name2]&&!this.isUnseen(1)){
						skills.addArray(lib.character[this.name2][3]);
					}
					return skills;
				},
				getModableSkills:function(useCache){
					var func = function(player){
						var skills=player.getSkills().concat(lib.skill.global);
						game.expandSkills(skills);
						skills = skills.filter(function(skill){
							var info = get.info(skill);
							return info && info.mod;
						});
						skills.sort((a,b)=>get.priority(a)-get.priority(b));
						return skills;
					};
					if(!useCache)return func(this);
					return game.callFuncUseStepCache("player.getModableSkills",func,[this]);
				},
				getSkills:function(arg2,arg3,arg4){
					var skills=this.skills.slice(0);
					var es=[];
					var i,j;
					if(arg3!==false){
						for(i=0;i<this.node.equips.childElementCount;i++){
							if(!this.node.equips.childNodes[i].classList.contains('removing')){
								var equipskills=get.info(this.node.equips.childNodes[i],false).skills;
								if(equipskills){
									es.addArray(equipskills);
								}
							}
						}
						if(arg2=='e'){
							return es;
						}
					}
					for(var i in this.additionalSkills){
						if(Array.isArray(this.additionalSkills[i])&&(arg2||i.indexOf('hidden:')!==0)){
							for(j=0;j<this.additionalSkills[i].length;j++){
								if(this.additionalSkills[i][j]){
									skills.add(this.additionalSkills[i][j]);
								}
							}
						}
						else if(this.additionalSkills[i]&&typeof this.additionalSkills[i]=='string'){
							skills.add(this.additionalSkills[i]);
						}
					}
					for(var i in this.tempSkills){
						skills.add(i);
					}
					if(arg2) skills.addArray(this.hiddenSkills);
					if(arg2===false||arg2=='invisible') skills.addArray(this.invisibleSkills);
					if(arg3!==false) skills.addArray(es);
					for(var i in this.forbiddenSkills){
						skills.remove(i);
					}
					if(arg4!==false){
						skills=game.filterSkills(skills,this,es);
					}
					return skills;
				},
				get:function(arg1,arg2,arg3,arg4){
					var i,j;
					if(arg1=='s'){
						var skills=this.skills.slice(0);
						var es=[];
						if(arg3!==false){
							for(i=0;i<this.node.equips.childElementCount;i++){
								if(!this.node.equips.childNodes[i].classList.contains('removing')&&!this.node.equips.childNodes[i].classList.contains('feichu')){
									var equipskills=get.info(this.node.equips.childNodes[i]).skills;
									if(equipskills){
										es.addArray(equipskills);
									}
								}
							}
							if(arg2=='e'){
								return es;
							}
						}
						for(var i in this.additionalSkills){
							if(Array.isArray(this.additionalSkills[i])){
								for(j=0;j<this.additionalSkills[i].length;j++){
									if(this.additionalSkills[i][j]){
										skills.add(this.additionalSkills[i][j]);
									}
								}
							}
							else if(this.additionalSkills[i]&&typeof this.additionalSkills[i]=='string'){
								skills.add(this.additionalSkills[i]);
							}
						}
						for(var i in this.tempSkills){
							skills.add(i);
						}
						if(arg2) skills.addArray(this.hiddenSkills);
						if(arg3!==false) skills.addArray(es);
						for(var i in this.forbiddenSkills){
							skills.remove(i);
						}
						if(arg4!==false){
							skills=game.filterSkills(skills,this,es);
						}
						return skills;
					}
					else if(get.is.pos(arg1)){
						var cards=[],cards1=[];
						for(i=0;i<arg1.length;i++){
							if(arg1[i]=='h'){
								for(j=0;j<this.node.handcards1.childElementCount;j++){
									if(!this.node.handcards1.childNodes[j].classList.contains('removing')&&!this.node.handcards1.childNodes[j].classList.contains('feichu')&&!this.node.handcards1.childNodes[j].classList.contains('glows')){
										cards.push(this.node.handcards1.childNodes[j]);
									}
								}
								for(j=0;j<this.node.handcards2.childElementCount;j++){
									if(!this.node.handcards2.childNodes[j].classList.contains('removing')&&!this.node.handcards2.childNodes[j].classList.contains('feichu')&&!this.node.handcards2.childNodes[j].classList.contains('glows')){
										cards.push(this.node.handcards2.childNodes[j]);
									}
								}
							}
							else if(arg1[i]=='e'){
								for(j=0;j<this.node.equips.childElementCount;j++){
									if(!this.node.equips.childNodes[j].classList.contains('removing')&&!this.node.equips.childNodes[j].classList.contains('feichu')){
										cards.push(this.node.equips.childNodes[j]);
									}
								}
								if(arguments.length==2&&typeof arg2=='string'&&/1|2|3|4|5/.test(arg2)){
									for(j=0;j<cards.length;j++){
										if(get.subtype(cards[j])=='equip'+arg2) return cards[j];
									}
									return;
								}
							}
							else if(arg1[i]=='j'){
								for(j=0;j<this.node.judges.childElementCount;j++){
									if(!this.node.judges.childNodes[j].classList.contains('removing')&&!this.node.judges.childNodes[j].classList.contains('feichu')){
										cards.push(this.node.judges.childNodes[j]);
										if(this.node.judges.childNodes[j].viewAs&&arguments.length>1){
											this.node.judges.childNodes[j].tempJudge=this.node.judges.childNodes[j].name;
											this.node.judges.childNodes[j].name=this.node.judges.childNodes[j].viewAs;
											cards1.push(this.node.judges.childNodes[j]);
										}
									}
								}
							}
						}
						if(arguments.length==1){
							return cards;
						}
						if(arg2!=undefined){
							if(typeof arg3=='function'){
								var cards2=cards.slice(0);
								cards.sort(function(a,b){
									return arg3(b,cards2)-arg3(a,cards2);
								});
							}
							if(typeof arg2=='string'){
								for(i=0;i<cards.length;i++){
									if(cards[i].name!=arg2){
										cards.splice(i,1);i--;
									}
								}
							}
							else if(typeof arg2=='object'){
								for(i=0;i<cards.length;i++){
									for(j in arg2){
										if(j=='type'){
											if(typeof arg2[j]=='object'){
												if(arg2[j].contains(get.type(cards[i]))==false){
													cards.splice(i,1);i--;break;
												}
											}
											else if(typeof arg2[j]=='string'){
												if(get.type(cards[i])!=arg2[j]){
													cards.splice(i,1);i--;break;
												}
											}
										}
										else if(j=='subtype'){
											if(typeof arg2[j]=='object'){
												if(arg2[j].contains(get.subtype(cards[i]))==false){
													cards.splice(i,1);i--;break;
												}
											}
											else if(typeof arg2[j]=='string'){
												if(get.subtype(cards[i])!=arg2[j]){
													cards.splice(i,1);i--;break;
												}
											}
										}
										else if(j=='color'){
											if(typeof arg2[j]=='object'){
												if(arg2[j].contains(get.color(cards[i]))==false){
													cards.splice(i,1);i--;break;
												}
											}
											else if(typeof arg2[j]=='string'){
												if(get.color(cards[i])!=arg2[j]){
													cards.splice(i,1);i--;break;
												}
											}
										}
										else if(j=='suit'){
											if(typeof arg2[j]=='object'){
												if(arg2[j].contains(get.suit(cards[i]))==false){
													cards.splice(i,1);i--;break;
												}
											}
											else if(typeof arg2[j]=='string'){
												if(get.suit(cards[i])!=arg2[j]){
													cards.splice(i,1);i--;break;
												}
											}
										}
										else if(j=='number'){
											if(typeof arg2[j]=='object'){
												if(arg2[j].contains(get.number(cards[i]))==false){
													cards.splice(i,1);i--;break;
												}
											}
											else if(typeof arg2[j]=='string'){
												if(get.number(cards[i])!=arg2[j]){
													cards.splice(i,1);i--;break;
												}
											}
										}
										else if(typeof arg2[j]=='object'){
											if(arg2[j].contains(cards[i][j])==false){
												cards.splice(i,1);i--;break;
											}
										}
										else if(typeof arg2[j]=='string'){
											if(cards[i][j]!=arg2[j]){
												cards.splice(i,1);i--;break;
											}
										}
									}
								}
							}
							else if(typeof arg2=='number'&&arg2>0){
								cards.splice(arg2);
							}
							else if(typeof arg2=='function'){
								for(i=0;i<cards.length;i++){
									if(!arg2(cards[i])){
										cards.splice(i,1);i--;
									}
								}
							}
						}
						for(i=0;i<cards1.length;i++){
							if(cards1[i].tempJudge){
								cards1[i].name=cards1[i].tempJudge;
								delete cards1[i].tempJudge;
							}
						}
						if(arg2===0) return cards[0];
						if(typeof arg3=='number'){
							if(arg3==0) return cards[0];
							cards.splice(arg3);
						}
						if(typeof arg4=='number'){
							if(arg4==0) return cards[0];
							cards.splice(arg4);
						}
						return cards;
					}
				},
				syncStorage:function(skill){
					switch(get.itemtype(this.storage[skill])){
						case 'cards':game.addVideo('storage',this,[skill,get.cardsInfo(this.storage[skill]),'cards']);break;
						case 'card':game.addVideo('storage',this,[skill,get.cardInfo(this.storage[skill]),'card']);break;
						default:
						try{
							game.addVideo('storage',this,[skill,JSON.parse(JSON.stringify(this.storage[skill]))]);
						}
						catch(e){
							console.log(this.storage[skill]);
						}
					}
				},
				syncSkills:function(){
					game.broadcast(function(player,skills){
						player.applySkills(skills);
					},this,get.skillState(this));
				},
				playerfocus:function(time){
					time=time||1000;
					this.classList.add('playerfocus');
					ui.arena.classList.add('playerfocus');
					var that=this;
					setTimeout(function(){
						that.classList.remove('playerfocus');
						ui.arena.classList.remove('playerfocus');
					},time);
					game.addVideo('playerfocus',this,time);
					game.broadcast(function(player,time){
						player.playerfocus(time);
					},this,time);
					return this;
				},
				setIdentity:function(identity,nature){
					if(!identity) identity=this.identity;
					if(get.is.jun(this)){
						this.node.identity.firstChild.innerHTML='君';
					}
					else{
						this.node.identity.firstChild.innerHTML=get.translation(identity);
					}
					this.node.identity.dataset.color=nature||identity;
					return this;
				},
				insertPhase:function(skill,insert){
					var evt=_status.event.getParent('phase');
					var next;
					if(evt&&evt.parent&&evt.parent.next){
						evt=evt.parent;
						next=game.createEvent('phase',false,evt);
					}
					else if(_status.event.parent&&_status.event.parent.next){
						evt=_status.event.parent;
						next=game.createEvent('phase',false,evt);
					}
					else{
						evt=null;
						next=game.createEvent('phase',false);
					}
					if(evt&&insert&&evt.next.contains(next)){
						evt.next.remove(next);
						evt.next.unshift(next);
					}
					next.player=this;
					next.forceDie=true;
					next.includeOut=true;
					next.skill=skill||_status.event.name;
					next.setContent('phase');
					return next;
				},
				insertEvent:function(name,content,arg){
					var evt=_status.event.getParent('phase');
					var next;
					if(evt&&evt.parent&&evt.parent.next){
						next=game.createEvent(name,null,evt.parent);
					}
					else{
						next=game.createEvent(name);
					}
					for(var i in arg){
						next[i]=arg[i];
					}
					next.player=this;
					next.setContent(content);
					return next;
				},
				phase:function(skill){
					var next=game.createEvent('phase',false);
					next.player=this;
					next.setContent('phase');
					if(!_status.roundStart){
						_status.roundStart=this;
					}
					if(skill){
						next.skill=skill;
					}
					next.forceDie=true;
					next.includeOut=true;
					return next;
				},
				phaseZhunbei:function(){
					var next=game.createEvent('phaseZhunbei');
					next.player=this;
					next.setContent('phaseZhunbei');
					return next;
				},
				phaseJudge:function(){
					var next=game.createEvent('phaseJudge');
					next.player=this;
					next.setContent('phaseJudge');
					return next;
				},
				phaseDraw:function(){
					var next=game.createEvent('phaseDraw');
					next.player=this;
					next.num=2;
					if((get.config('first_less')||_status.connectMode||_status.first_less_forced)&&game.phaseNumber==1&&_status.first_less){
						next.num--;
					}
					next.setContent('phaseDraw');
					return next;
				},
				phaseUse:function(){
					var next=game.createEvent('phaseUse');
					next.player=this;
					next.setContent('phaseUse');
					return next;
				},
				phaseDiscard:function(){
					var next=game.createEvent('phaseDiscard');
					next.player=this;
					next.setContent('phaseDiscard');
					return next;
				},
				phaseJieshu:function(){
					var next=game.createEvent('phaseJieshu');
					next.player=this;
					next.setContent('phaseJieshu');
					return next;
				},
				chooseToUse:function(use){
					var next=game.createEvent('chooseToUse');
					next.player=this;
					if(arguments.length==1&&get.objtype(arguments[0])=='object'){
						for(var i in use){
							next[i]=use[i];
						}
					}
					else{
						for(var i=0;i<arguments.length;i++){
							if(typeof arguments[i]=='number'||get.itemtype(arguments[i])=='select'){
								next.selectTarget=arguments[i];
							}
							else if((typeof arguments[i]=='object'&&arguments[i])||typeof arguments[i]=='function'){
								if(get.itemtype(arguments[i])=='player'||next.filterCard){
									next.filterTarget=arguments[i];
								}
								else next.filterCard=arguments[i];
							}
							else if(typeof arguments[i]=='boolean'){
								next.forced=arguments[i];
							}
							else if(typeof arguments[i]=='string'){
								next.prompt=arguments[i];
							}
						}
					}
					if(typeof next.filterCard=='object'){
						next.filterCard=get.filter(next.filterCard);
					}
					if(typeof next.filterTarget=='object'){
						next.filterTarget=get.filter(next.filterTarget,2);
					}
					if(next.filterCard==undefined){
						next.filterCard=lib.filter.filterCard;
					}
					if(next.selectCard==undefined){
						next.selectCard=[1,1];
					}
					if(next.filterTarget==undefined){
						next.filterTarget=lib.filter.filterTarget;
					}
					if(next.selectTarget==undefined){
						next.selectTarget=lib.filter.selectTarget;
					}
					if(next.position==undefined){
						next.position='hs';
					}
					if(next.ai1==undefined) next.ai1=get.order;
					if(next.ai2==undefined) next.ai2=get.effect_use;
					next.setContent('chooseToUse');
					next._args=Array.from(arguments);
					return next;
				},
				chooseToRespond:function(){
					var next=game.createEvent('chooseToRespond');
					next.player=this;
					var filter;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							next.selectCard=[arguments[i],arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectCard=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							next.position=arguments[i];
						}
						else if(typeof arguments[i]=='function'){
							if(next.filterCard) next.ai=arguments[i];
							else next.filterCard=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]){
							next.filterCard=get.filter(arguments[i]);
							filter=arguments[i];
						}
						else if(arguments[i]=='nosource'){
							next.nosource=true;
						}
						else if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
					}
					if(next.filterCard==undefined) next.filterCard=lib.filter.all;
					if(next.selectCard==undefined) next.selectCard=[1,1];
					if(next.source==undefined&&!next.nosource) next.source=_status.event.player;
					if(next.ai==undefined) next.ai=get.unuseful2;
					if(next.prompt!=false){
						if(typeof next.prompt=='string'){
							//next.dialog=next.prompt;
						}
						else{
							var str='请打出'+get.cnNumber(next.selectCard[0])+'张'
							if(filter){
								if(filter.name){
									str+=get.translation(filter.name);
								}
								else{
									str+='牌';
								}
							}
							else{
								str+='牌';
							}
							if(_status.event.getParent().name=='useCard'){
								var cardname=_status.event.name;
								if(lib.card[cardname]&&lib.translate[cardname]){
									str+='响应'+lib.translate[cardname];
								}
							}
							next.prompt=str;
						}
					}
					next.position='hs';
					if(next.ai2==undefined) next.ai2=(()=>1);
					next.setContent('chooseToRespond');
					next._args=Array.from(arguments);
					return next;
				},
				chooseToDiscard:function(){
					var next=game.createEvent('chooseToDiscard');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							next.selectCard=[arguments[i],arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectCard=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='dialog'){
							next.dialog=arguments[i];
							next.prompt=false;
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							next.position=arguments[i];
						}
						else if(typeof arguments[i]=='function'){
							if(next.filterCard) next.ai=arguments[i];
							else next.filterCard=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]){
							next.filterCard=get.filter(arguments[i]);
						}
						else if(typeof arguments[i]=='string'){
							get.evtprompt(next,arguments[i]);
						}
						if(arguments[i]===null){
							for(var i=0;i<arguments.length;i++){
								console.log(arguments[i]);
							}
						}
					}
					if(next.isMine()==false&&next.dialog) next.dialog.style.display='none';
					if(next.filterCard==undefined) next.filterCard=lib.filter.all;
					if(next.selectCard==undefined) next.selectCard=[1,1];
					if(next.ai==undefined) next.ai=get.unuseful;
					next.autochoose=function(){
						if(!this.forced) return false;
						if(typeof this.selectCard=='function') return false;
						var cards=this.player.getCards(this.position);
						var num=cards.length;
						for(var i=0;i<cards.length;i++){
							if(!lib.filter.cardDiscardable(cards[i],this.player,this)) num--;
						}
						return get.select(this.selectCard)[0]>=num;
					}
					next.setContent('chooseToDiscard');
					next._args=Array.from(arguments);
					return next;
				},
				chooseToCompare:function(target,check){
					var next=game.createEvent('chooseToCompare');
					next.player=this;
					if(Array.isArray(target)){
						next.targets=target;
						if(check) next.ai=check;
						else next.ai=function(card){
							if(typeof card=='string'&&lib.skill[card]){
								var ais=lib.skill[card].check||function(){return 0};
								return ais();
							}
							var addi=(get.value(card)>=8&&get.type(card)!='equip')?-3:0;
							if(card.name=='du') addi-=3;
							var source=_status.event.source;
							var player=_status.event.player;
							var event=_status.event.getParent();
							var getn=function(card){
								if(player.hasSkill('tianbian')&&get.suit(card)=='heart') return 13*(Boolean(event.small)?-1:1);
								return get.number(card)*(Boolean(event.small)?-1:1);
							}
							if(source&&source!=player){
								if(get.attitude(player,source)>1){
									if(Boolean(event.small)) return getn(card)-get.value(card)/2+addi;
									return -getn(card)-get.value(card)/2+addi;
								}
								if(Boolean(event.small)) return -getn(card)-get.value(card)/2+addi;
								return getn(card)-get.value(card)/2+addi;
							}
							else{
								if(Boolean(event.small)) return -getn(card)-get.value(card)/2+addi;
								return getn(card)-get.value(card)/2+addi;
							}
						}
						next.setContent('chooseToCompareMultiple');
					}
					else{
						next.target=target;
						if(check) next.ai=check;
						else next.ai=function(card){
							if(typeof card=='string'&&lib.skill[card]){
								var ais=lib.skill[card].check||function(){return 0};
								return ais();
							}
							var player=get.owner(card);
							var getn=function(card){
								if(player.hasSkill('tianbian')&&get.suit(card)=='heart') return 13;
								return get.number(card);
							}
							var event=_status.event.getParent();
							var to=(player==event.player?event.target:event.player);
							var addi=(get.value(card)>=8&&get.type(card)!='equip')?-6:0;
							if(card.name=='du') addi-=5;
							if(player==event.player){
								if(Boolean(event.small)){
									return -getn(card)-get.value(card)/2+addi;
								}
								return getn(card)-get.value(card)/2+addi;
							}
							else{
								if((get.attitude(player,to)<=0)==Boolean(event.small)){
									return -getn(card)-get.value(card)/2+addi;
								}
								return getn(card)-get.value(card)/2+addi;
							}
						}
						next.setContent('chooseToCompare');
					}
					next.forceDie=true;
					next._args=Array.from(arguments);
					return next;
				},
				chooseSkill:function(target){
					var next=game.createEvent('chooseSkill');
					next.player=this;
					next.setContent('chooseSkill');
					next.target=target;
					for(var i=1;i<arguments.length;i++){
						if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
						else if(typeof arguments[i]=='function'){
							next.func=arguments[i];
						}
					}
				},
				discoverCard:function(list){
					var next=game.createEvent('discoverCard');
					next.player=this;
					next.setContent('discoverCard');
					next.list=list||lib.inpile.slice(0);
					next.forced=true;
					for(var i=1;i<arguments.length;i++){
						if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							switch(arguments[i]){
								case 'use': next.use=true; break;
								case 'nogain': next.nogain=true; break;
								default: next.prompt=arguments[i];
							}
						}
						else if(typeof arguments[i]=='number'){
							next.num=arguments[i];
						}
						else if(typeof arguments[i]==='function'){
							next.ai=arguments[i];
						}
					}
					return next;
				},
				chooseCardButton:function(){
					var cards,prompt,forced,select;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards') cards=arguments[i];
						else if(typeof arguments[i]=='boolean') forced=arguments[i];
						else if(typeof arguments[i]=='string') prompt=arguments[i];
						else if(get.itemtype(arguments[i])=='select'||typeof arguments[i]=='number') select=arguments[i];
					}
					if(prompt==undefined) prompt='请选择卡牌';
					return this.chooseButton(forced,select,'hidden',[prompt,cards,'hidden']);
				},
				chooseVCardButton:function(){
					var list,prompt,forced,select,notype=false;
					for(var i=0;i<arguments.length;i++){
						if(Array.isArray(arguments[i])){
							list=arguments[i];
						}
						else if(arguments[i]=='notype'){
							notype=true;
						}
						else if(typeof arguments[i]=='boolean') forced=arguments[i];
						else if(typeof arguments[i]=='string') prompt=arguments[i];
						else if(get.itemtype(arguments[i])=='select'||typeof arguments[i]=='number') select=arguments[i];
					}
					for(var i=0;i<list.length;i++){
						list[i]=[notype?'':(get.subtype(list[i])||get.type(list[i])),'',list[i]];
					}
					if(prompt==undefined) prompt='请选择卡牌';
					return this.chooseButton(forced,select,'hidden',[prompt,[list,'vcard'],'hidden']);
				},
				chooseButton:function(){
					var next=game.createEvent('chooseButton');
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='dialog'){
							next.dialog=arguments[i];
							next.closeDialog=true;
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectButton=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.selectButton=[arguments[i],arguments[i]];
						}
						else if(typeof arguments[i]=='function'){
							if(next.ai) next.filterButton=arguments[i];
							else next.ai=arguments[i];
						}
						else if(Array.isArray(arguments[i])){
							next.createDialog=arguments[i];
						}
					}
					next.player=this;
					if(typeof next.forced!='boolean') next.forced=false;
					if(next.isMine()==false&&next.dialog) next.dialog.style.display='none';
					if(next.filterButton==undefined) next.filterButton=lib.filter.filterButton;
					if(next.selectButton==undefined) next.selectButton=[1,1];
					if(next.ai==undefined) next.ai=function(){return 1};
					next.setContent('chooseButton');
					next._args=Array.from(arguments);
					next.forceDie=true;
					return next;
				},
				chooseButtonOL:function(list,callback,ai){
					var next=game.createEvent('chooseButtonOL');
					next.list=list;
					next.setContent('chooseButtonOL');
					next.ai=ai;
					next.callback=callback;
					next._args=Array.from(arguments);
					return next;
				},
				chooseCardOL:function(){
					var next=game.createEvent('chooseCardOL');
					next._args=[];
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='players'){
							next.list=arguments[i].slice(0);
						}
						else{
							next._args.push(arguments[i]);
						}
					}
					next.setContent('chooseCardOL');
					next._args.add('glow_result');
					return next;
				},
				chooseCard:function(choose){
					var next=game.createEvent('chooseCard');
					next.player=this;
					if(arguments.length==1&&get.is.object(choose)){
						for(var i in choose){
							next[i]=choose[i];
						}
					}
					else{
						for(var i=0;i<arguments.length;i++){
							if(typeof arguments[i]=='number'){
								next.selectCard=[arguments[i],arguments[i]];
							}
							else if(get.itemtype(arguments[i])=='select'){
								next.selectCard=arguments[i];
							}
							else if(typeof arguments[i]=='boolean'){
								next.forced=arguments[i];
							}
							else if(get.itemtype(arguments[i])=='position'){
								next.position=arguments[i];
							}
							else if(typeof arguments[i]=='function'){
								if(next.filterCard) next.ai=arguments[i];
								else next.filterCard=arguments[i];
							}
							else if(typeof arguments[i]=='object'&&arguments[i]){
								next.filterCard=get.filter(arguments[i]);
							}
							else if(arguments[i]=='glow_result'){
								next.glow_result=true;
							}
							else if(typeof arguments[i]=='string'){
								get.evtprompt(next,arguments[i]);
							}
						}
					}
					if(next.filterCard==undefined) next.filterCard=lib.filter.all;
					if(next.selectCard==undefined) next.selectCard=[1,1];
					if(next.ai==undefined) next.ai=get.unuseful3;
					next.setContent('chooseCard');
					next._args=Array.from(arguments);
					return next;
				},
				chooseUseTarget:function(){
					var next=game.createEvent('chooseUseTarget');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='players'){
							next.targets=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='player'){
							next.targets=[arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectTarget=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.selectTarget=[arguments[i],arguments[i]];
						}
						else if(get.is.object(arguments[i])&&arguments[i].name){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							if(arguments[i]=='nopopup'){
								next.nopopup=true;
							}
							else if(arguments[i]=='noanimate'){
								next.animate=false;
							}
							else if(arguments[i]=='nothrow'){
								next.throw=false;
							}
							else if(arguments[i]=='nodistance'){
								next.nodistance=true;
							}
							else if(arguments[i]=='noTargetDelay'){
								next.noTargetDelay=true;
							}
							else if(arguments[i]=='nodelayx'){
								next.nodelayx=true;
							}
							else if(lib.card[arguments[i]]&&!next.card){
								next.card={name:arguments[i],isCard:true};
							}
							else get.evtprompt(next,arguments[i]);
						}
						else if(arguments[i]===true){
							next.forced=true;
						}
						else if(arguments[i]===false){
							next.addCount=false;
						}
					}
					if(!next.targets) next.targets=game.players.slice(0);
					if(next.cards==undefined){
						if(get.itemtype(next.card)=='card'){
							next.cards=[next.card];
						}
						else next.cards=[];
					}
					else if(next.card==undefined){
						if(next.cards){
							next.card=next.cards[0];
						}
					}
					next.setContent('chooseUseTarget');
					next._args=Array.from(arguments);
					return next;
					// Fully Online-Ready! Enjoy It!
				},
				chooseTarget:function(){
					var next=game.createEvent('chooseTarget');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							next.selectTarget=[arguments[i],arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectTarget=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='dialog'){
							next.dialog=arguments[i];
							next.prompt=false;
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(typeof arguments[i]=='function'){
							if(next.filterTarget) next.ai=arguments[i];
							else next.filterTarget=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							get.evtprompt(next,arguments[i]);
						}
					}
					if(next.filterTarget==undefined) next.filterTarget=lib.filter.all;
					if(next.selectTarget==undefined) next.selectTarget=[1,1];
					if(next.ai==undefined) next.ai=get.attitude2;
					next.setContent('chooseTarget');
					next._args=Array.from(arguments);
					next.forceDie=true;
					return next;
				},
				chooseCardTarget:function(choose){
					var next=game.createEvent('chooseCardTarget');
					next.player=this;
					if(arguments.length==1){
						for(var i in choose){
							next[i]=choose[i];
						}
					}
					if(typeof next.filterCard=='object'){
						next.filterCard=get.filter(next.filterCard);
					}
					if(typeof next.filterTarget=='object'){
						next.filterTarget=get.filter(next.filterTarget,2);
					}
					if(next.filterCard==undefined||next.filterCard===true){
						next.filterCard=lib.filter.all;
					}
					if(next.selectCard==undefined){
						next.selectCard=1;
					}
					if(next.filterTarget==undefined||next.filterTarget===true){
						next.filterTarget=lib.filter.all;
					}
					if(next.selectTarget==undefined){
						next.selectTarget=1;
					}
					if(next.ai1==undefined) next.ai1=get.unuseful2;
					if(next.ai2==undefined) next.ai2=get.attitude2;
					next.setContent('chooseCardTarget');
					next._args=Array.from(arguments);
					return next;
				},
				chooseControlList:function(){
					var list=[];
					var prompt=null;
					var forced='cancel2';
					var func=null;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='string'){
							if(!prompt){
								prompt=arguments[i];
							}
							else{
								list.push(arguments[i]);
							}
						}
						else if(Array.isArray(arguments[i])){
							list=arguments[i];
						}
						else if(arguments[i]===true){
							forced=null;
						}
						else if(typeof arguments[i]=='function'){
							func=arguments[i];
						}
					}
					return this.chooseControl(forced,func).set('choiceList',list).set('prompt',prompt);
				},
				chooseControl:function(){
					var next=game.createEvent('chooseControl');
					next.controls=[];
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='string'){
							if(arguments[i]=='dialogcontrol'){
								next.dialogcontrol=true;
							}
							else if(arguments[i]=='seperate'){
								next.seperate=true;
							}
							else{
								next.controls.push(arguments[i]);
							}
						}
						else if(Array.isArray(arguments[i])){
							next.controls=next.controls.concat(arguments[i]);
						}
						else if(typeof arguments[i]=='function'){
							next.ai=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.choice=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='dialog'){
							next.dialog=arguments[i];
						}
					}
					next.player=this;
					if(next.choice==undefined) next.choice=0;
					next.setContent('chooseControl');
					next._args=Array.from(arguments);
					next.forceDie=true;
					return next;
				},
				chooseBool:function(){
					var next=game.createEvent('chooseBool');
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='boolean'){
							next.choice=arguments[i];
						}
						else  if(typeof arguments[i]=='function'){
							next.ai=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							get.evtprompt(next,arguments[i]);
						}
						else if(get.itemtype(arguments[i])=='dialog'){
							next.dialog=arguments[i];
						}
						if(next.choice==undefined) next.choice=true;
					}
					next.player=this;
					next.setContent('chooseBool');
					next._args=Array.from(arguments);
					next.forceDie=true;
					return next;
				},
				chooseDrawRecover:function(){
					var next=game.createEvent('chooseDrawRecover',false);
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							if(typeof next.num1=='number'){
								next.num2=arguments[i];
							}
							else{
								next.num1=arguments[i];
							}
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
						else if(typeof arguments[i]=='function'){
							next.ai=arguments[i];
						}
					}
					if(typeof next.num1!='number'){
						next.num1=1;
					}
					if(typeof next.num2!='number'){
						next.num2=1;
					}
					next.setContent('chooseDrawRecover');
					return next;
				},
				choosePlayerCard:function(){
					var next=game.createEvent('choosePlayerCard');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.target=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.selectButton=[arguments[i],arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectButton=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							next.position=arguments[i];
						}
						else if(arguments[i]=='visible'){
							next.visible=true;
						}
						else if(typeof arguments[i]=='function'){
							if(next.ai) next.filterButton=arguments[i];
							else next.ai=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]){
							next.filterButton=get.filter(arguments[i]);
						}
						else if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
					}
					if(next.filterButton==undefined) next.filterButton=lib.filter.all;
					if(next.position==undefined) next.position='he';
					if(next.selectButton==undefined) next.selectButton=[1,1];
					if(next.ai==undefined) next.ai=function(button){
						var val=get.buttonValue(button);
						if(get.attitude(_status.event.player,get.owner(button.link))>0) return -val;
						return val;
					};
					next.setContent('choosePlayerCard');
					next._args=Array.from(arguments);
					return next;
				},
				discardPlayerCard:function(){
					var next=game.createEvent('discardPlayerCard');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.target=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.selectButton=[arguments[i],arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectButton=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							next.position=arguments[i];
						}
						else if(arguments[i]=='visible'){
							next.visible=true;
						}
						else if(typeof arguments[i]=='function'){
							if(next.ai) next.filterButton=arguments[i];
							else next.ai=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]){
							next.filterButton=get.filter(arguments[i]);
						}
						else if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
					}
					if(next.filterButton==undefined) next.filterButton=lib.filter.all;
					if(next.position==undefined) next.position='he';
					if(next.selectButton==undefined) next.selectButton=[1,1];
					if(next.ai==undefined) next.ai=function(button){
						var val=get.buttonValue(button);
						if(get.attitude(_status.event.player,get.owner(button.link))>0) return -val;
						return val;
					};
					next.setContent('discardPlayerCard');
					next._args=Array.from(arguments);
					return next;
				},
				gainPlayerCard:function(){
					var next=game.createEvent('gainPlayerCard');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.target=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.selectButton=[arguments[i],arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='select'){
							next.selectButton=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							next.position=arguments[i];
						}
						else if(arguments[i]=='visible'){
							next.visible=true;
						}
						else if(arguments[i]=='visibleMove'){
							next.visibleMove=true;
						}
						else if(typeof arguments[i]=='function'){
							if(next.ai) next.filterButton=arguments[i];
							else next.ai=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]){
							next.filterButton=get.filter(arguments[i]);
						}
						else if(typeof arguments[i]=='string'){
							next.prompt=arguments[i];
						}
					}
					if(next.filterButton==undefined) next.filterButton=lib.filter.all;
					if(next.position==undefined) next.position='he';
					if(next.selectButton==undefined) next.selectButton=[1,1];
					if(next.ai==undefined) next.ai=function(button){
						var val=get.buttonValue(button);
						if(get.attitude(_status.event.player,get.owner(button.link))>0) return -val;
						return val;
					};
					next.setContent('gainPlayerCard');
					next._args=Array.from(arguments);
					return next;
				},
				showHandcards:function(str){
					var next=game.createEvent('showHandcards');
					next.player=this;
					if(typeof str=='string'){
						next.prompt=str;
					}
					next.setContent('showHandcards');
					next._args=Array.from(arguments);
					return next;
				},
				showCards:function(cards,str){
					var next=game.createEvent('showCards');
					next.player=this;
					next.str=str;
					if(typeof cards=='string'){
						str=cards;
						cards=next.str;
						next.str=str;
					}
					if(get.itemtype(cards)=='card') next.cards=[cards];
					else if(get.itemtype(cards)=='cards') next.cards=cards.slice(0);
					else _status.event.next.remove(next);
					next.setContent('showCards');
					next._args=Array.from(arguments);
					return next;
				},
				viewCards:function(str,cards){
					var next=game.createEvent('viewCards');
					next.player=this;
					next.str=str;
					next.cards=cards.slice(0);
					next.setContent('viewCards');
					next._args=Array.from(arguments);
					return next;
				},
				viewHandcards:function(target){
					var cards=target.getCards('h');
					if(cards.length){
						return this.viewCards(get.translation(target)+'的手牌',cards);
					}
					else{
						return false;
					}
				},
				canMoveCard:function(withatt,nojudge){
					var player=this;
					return game.hasPlayer(function(current){
						var att=get.sgn(get.attitude(player,current));
						if(!withatt||att!=0){
							var es=current.getCards('e');
							for(var i=0;i<es.length;i++){
								if(game.hasPlayer(function(current2){
									if(withatt){
										if(get.sgn(get.value(es[i],current))!=-att) return false;
										var att2=get.sgn(get.attitude(player,current2));
										if(att==att2||att2!=get.sgn(get.effect(current2,es[i],player,current2))) return false;
									}
									return current!=current2&&!current2.isMin()&&current2.canEquip(es[i]);
								})){
									return true;
								}
							}
						}
						if(!nojudge&&(!withatt||att>0)){
							var js=current.getCards('j');
							for(var i=0;i<js.length;i++){
								if(game.hasPlayer(function(current2){
									if(withatt){
										var att2=get.attitude(player,current2);
										if(att2>=0) return false;
									}
									return current!=current2&&current2.canAddJudge(js[i]);
								})){
									return true;
								}
							}
						}
					});
				},
				moveCard:function(){
					var next=game.createEvent('moveCard');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='boolean'){
							next.forced=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							get.evtprompt(next,arguments[i]);
						}
						else if(Array.isArray(arguments[i])){
							for(var j=0;j<arguments[i].length;j++){
								if(typeof arguments[i][j]!='string') break;
							}
							if(j==arguments[i].length){
								next.targetprompt=arguments[i];
							}
						}
					}
					next.setContent('moveCard');
					next._args=Array.from(arguments);
					return next;
				},
				useResult:function(result,event){
					event=event||_status.event;
					if(result._sendskill){
						lib.skill[result._sendskill[0]]=result._sendskill[1];
					}
					if(event.onresult){
						event.onresult(result);
					}
					if(result.skill){
						var info=get.info(result.skill);
						if(info.onuse){
							info.onuse(result,this);
						}
						if(info.direct&&!info.clearTime){
							_status.noclearcountdown=true;
						}
					}
					if(event.logSkill){
						if(typeof event.logSkill=='string'){
							this.logSkill(event.logSkill);
						}
						else if(Array.isArray(event.logSkill)){
							this.logSkill.apply(this,event.logSkill);
						}
					}
					if(result.card||!result.skill){
						result.used=result.card||result.cards[0];
						var next=this.useCard(result.used,result.cards,result.targets,result.skill);
						next.oncard=event.oncard;
						next.respondTo=event.respondTo;
						if(event.addCount===false){
							next.addCount=false;
						}
						if(result._apply_args){
							for(var i in result._apply_args){
								next[i]=result._apply_args[i];
							}
						}
						return next;
					}
					else if(result.skill){
						result.used=result.skill;
						return this.useSkill(result.skill,result.cards,result.targets);
					}
				},
				useCard:function(){
					var next=game.createEvent('useCard');
					next.player=this;
					next.num=0;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='players'){
							next.targets=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='player'){
							next.targets=[arguments[i]];
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]&&arguments[i].name){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							if(arguments[i]=='noai'){
								next.noai=true;
							}
							else if(arguments[i]=='nowuxie'){
								next.nowuxie=true;
							}
							else{
								next.skill=arguments[i];
							}
						}
						else if(typeof arguments[i]=='boolean'){
							next.addCount=arguments[i];
						}
					}
					if(next.cards==undefined){
						if(get.itemtype(next.card)=='card'){
							next.cards=[next.card];
						}
						else next.cards=[];
					}
					else if(next.card==undefined){
						if(next.cards){
							next.card=next.cards[0];
						}
					}
					if(!next.targets){
						next.targets=[];
					}
					if(next.card){
						next.card=get.autoViewAs(next.card,next.cards);
						var info=get.info(next.card);
						if(info.changeTarget){
							info.changeTarget(next.player,next.targets);
						}
						if(info.singleCard){
							next._targets=next.targets.slice(0);
							next.target=next.targets[0];
							next.addedTargets=next.targets.splice(1);
							if(next.addedTargets.length){
								next.addedTarget=next.addedTargets[0];
							}
						}
					}
					for(var i=0;i<next.targets.length;i++){
						if(get.attitude(this,next.targets[i])>=-1&&get.attitude(this,next.targets[i])<0){
							if(!this.ai.tempIgnore) this.ai.tempIgnore=[];
							this.ai.tempIgnore.add(next.targets[i]);
						}
					}
					if(typeof this.logAi=='function'&&!next.noai&&!get.info(next.card).noai){
						var postAi=get.info(next.card).postAi;
						if(postAi&&postAi(next.targets)){
							next.postAi=true;
						}
						else{
							this.logAi(next.targets,next.card);
						}
					}
					next.stocktargets=next.targets.slice(0);
					next.setContent('useCard');
					return next;
				},
				useSkill:function(){
					var next=game.createEvent('useSkill');
					next.player=this;
					next.num=0;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='players'){
							next.targets=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							next.skill=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.addCount=arguments[i];
						}
					}
					if(next.cards==undefined){
						next.cards=[];
					}
					if(next.skill&&get.info(next.skill)&&get.info(next.skill).changeTarget){
						get.info(next.skill).changeTarget(next.player,next.targets);
					}
					if(next.targets){
						for(var i=0;i<next.targets.length;i++){
							if(get.attitude(this,next.targets[i])>=-1&&get.attitude(this,next.targets[i])<0){
								if(!this.ai.tempIgnore) this.ai.tempIgnore=[];
								this.ai.tempIgnore.add(next.targets[i]);
							}
						}
						if(typeof this.logAi=='function'){
							this.logAi(next.targets,next.skill);
						}
					}
					else{
						next.targets=[];
					}
					next.setContent('useSkill');
					return next;
				},
				drawTo:function(num,args){
					var num2=num-this.countCards('h');
					if(!num2) return;
					var next=this.draw(num2);
					if(Array.isArray(args)){
						for(var i=0;i<args.length;i++){
							if(get.itemtype(args[i])=='player'){
								next.source=args[i];
							}
							else if(typeof args[i]=='boolean'){
								next.animate=args[i];
							}
							else if(args[i]=='nodelay'){
								next.animate=false;
								next.$draw=true;
							}
							else if(args[i]=='visible'){
								next.visible=true;
							}
							else if(args[i]=='bottom'){
								next.bottom=true;
							}
							else if(typeof args[i]=='object'&&args[i]&&args[i].drawDeck!=undefined){
								next.drawDeck=args[i].drawDeck;
							}
						}
					}
					return next;
				},
				draw:function(){
					var next=game.createEvent('draw');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.num=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.animate=arguments[i];
						}
						else if(arguments[i]=='nodelay'){
							next.animate=false;
							next.$draw=true;
						}
						else if(arguments[i]=='visible'){
							next.visible=true;
						}
						else if(arguments[i]=='bottom'){
							next.bottom=true;
						}
						else if(typeof arguments[i]=='object'&&arguments[i]&&arguments[i].drawDeck!=undefined){
							next.drawDeck=arguments[i].drawDeck;
						}
					}
					if(next.num==undefined) next.num=1;
					if(next.num<=0) _status.event.next.remove(next);
					next.setContent('draw');
					if(lib.config.mode=='stone'&&_status.mode=='deck'&&
					next.drawDeck==undefined&&!next.player.isMin()&&next.num>1){
						next.drawDeck=1;
					}
					next.result=[];
					return next;
				},
				randomDiscard:function(){
					var position='he',num=1,delay=null;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							num=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							position=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							delay=arguments[i];
						}
					}
					var cards=this.getCards(position).randomGets(num);
					if(cards.length){
						var next=this.discard(cards,'notBySelf');
						if(typeof delay=='boolean'){
							next.delay=delay;
						}
					}
					return cards;
				},
				randomGain:function(){
					var position='he',num=1,target=null,line=false;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							num=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='position'){
							position=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='player'){
							target=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							line=arguments[i];
						}
					}
					if(target){
						var cards=target.getCards(position).randomGets(num);
						if(cards.length){
							if(line){
								this.line(target,'green');
							}
							this.gain(cards,target,'log','bySelf');
							target.$giveAuto(cards,this);
						}
						return cards;
					}
					return [];
				},
				discard:function(){
					var next=game.createEvent('discard');
					next.player=this;
					next.num=0;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.cards=[arguments[i]];
						}
						else if(typeof arguments[i]=='boolean'){
							next.animate=arguments[i];
						}
						else if(get.objtype(arguments[i])=='div'){
							next.position=arguments[i];
						}
						else if(arguments[i]=='notBySelf'){
							next.notBySelf=true;
						}
					}
					if(next.cards==undefined) _status.event.next.remove(next);
					next.setContent('discard');
					return next;
				},
				loseToDiscardpile:function(){
					var next=game.createEvent('loseToDiscardpile');
					next.player=this;
					next.num=0;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.cards=[arguments[i]];
						}
						else if(typeof arguments[i]=='boolean'){
							next.animate=arguments[i];
						}
						else if(get.objtype(arguments[i])=='div'){
							next.position=arguments[i];
						}
						else if(arguments[i]=='notBySelf'){
							next.notBySelf=true;
						}
						else if(arguments[i]=='insert'){
							next.insert_card=true;
						}
						else if(arguments[i]=='blank'){
							next.blank=true;
						}
					}
					if(next.cards==undefined) _status.event.next.remove(next);
					next.setContent('loseToDiscardpile');
					return next;
				},
				respond:function(){
					var next=game.createEvent('respond');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]&&arguments[i].name){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='boolean') next.animate=arguments[i];
						else if(arguments[i]=='highlight') next.highlight=true;
						else if(arguments[i]=='noOrdering') next.noOrdering=true;
						else if(typeof arguments[i]=='string') next.skill=arguments[i];
					}
					if(next.cards==undefined){
						if(get.itemtype(next.card)=='card'){
							next.cards=[next.card];
						}
						else{
							next.cards=[];
						}
					}
					else if(next.card==undefined){
						if(next.cards){
							next.card=next.cards[0];
							if(!next.skill){
								next.card=get.autoViewAs(next.card,next.cards);
							}
						}
					}
					next.setContent('respond');
					return next;
				},
				swapHandcards:function(target,cards1,cards2){
					var next=game.createEvent('swapHandcards',false);
					next.player=this;
					next.target=target;
					if(cards1) next.cards1=cards1;
					if(cards2) next.cards2=cards2;
					next.setContent('swapHandcards');
					return next;
				},
				directequip:function(cards){
					for(var i=0;i<cards.length;i++){
						this.$equip(cards[i]);
					}
					if(!_status.video){
						game.addVideo('directequip',this,get.cardsInfo(cards));
					}
				},
				$addToExpansion:function(cards,broadcast,gaintag){
					var hs=this.getCards('x');
					for(var i=0;i<cards.length;i++){
						if(hs.contains(cards[i])){
							cards.splice(i--,1);
						}
					}
					for(var i=0;i<cards.length;i++){
						cards[i].fix();
						if(gaintag) cards[i].addGaintag(gaintag);
						var sort=lib.config.sort_card(cards[i]);
						this.node.expansions.insertBefore(cards[i],this.node.expansions.firstChild);
					}
					if(broadcast!==false) game.broadcast(function(player,cards,gaintag){
						player.$addToExpansion(cards,null,gaintag);
					},this,cards,gaintag);
					return this;
				},
				directgain:function(cards,broadcast,gaintag){
					var hs=this.getCards('hs');
					for(var i=0;i<cards.length;i++){
						if(hs.contains(cards[i])){
							cards.splice(i--,1);
						}
					}
					for(var i=0;i<cards.length;i++){
						cards[i].fix();
						if(gaintag) cards[i].addGaintag(gaintag);
						var sort=lib.config.sort_card(cards[i]);
						if(this==game.me){
							cards[i].classList.add('drawinghidden');
						}
						if(get.is.singleHandcard()||sort>0){
							this.node.handcards1.insertBefore(cards[i],this.node.handcards1.firstChild);
						}
						else{
							this.node.handcards2.insertBefore(cards[i],this.node.handcards2.firstChild);
						}
					}
					if(this==game.me||_status.video) ui.updatehl();
					if(!_status.video){
						game.addVideo('directgain',this,get.cardsInfo(cards));
						this.update();
					}
					if(broadcast!==false) game.broadcast(function(player,cards){
						player.directgain(cards);
					},this,cards);
					return this;
				},
				directgains:function(cards,broadcast,gaintag){
					var hs=this.getCards('hs');
					for(var i=0;i<cards.length;i++){
						if(hs.contains(cards[i])){
							cards.splice(i--,1);
						}
					}
					var addLast=function(card,node){
						if(gaintag){
							for(var i=0;i<node.childNodes.length;i++){
								var add=node.childNodes[node.childNodes.length-i-1];
								if(!add.classList.contains('glows')) break;
								if(add.hasGaintag(gaintag)){
									node.insertBefore(card,add.nextSibling);
									return;
								}
							}
						}
						node.appendChild(card);
					}
					for(var i=0;i<cards.length;i++){
						cards[i].fix();
						cards[i].remove();
						if(gaintag) cards[i].addGaintag(gaintag);
						cards[i].classList.add('glows');
						if(this==game.me){
							cards[i].classList.add('drawinghidden');
						}
						if(get.is.singleHandcard()){
							addLast(cards[i],this.node.handcards1);
						}
						else{
							addLast(cards[i],this.node.handcards2);
						}
					}
					if(this==game.me||_status.video) ui.updatehl();
					if(!_status.video){
						game.addVideo('directgains',this,get.cardsInfo(cards));
						this.update();
					}
					if(broadcast!==false) game.broadcast(function(player,cards,gaintag){
						player.directgains(cards,null,gaintag);
					},this,cards,gaintag);
					return this;
				},
				gainMultiple:function(targets,position){
					var next=game.createEvent('gainMultiple',false);
					next.setContent('gainMultiple');
					next.player=this;
					next.targets=targets;
					next.position=position||'h';
					return next;
				},
				gain:function(){
					var next=game.createEvent('gain');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.cards=[arguments[i]];
						}
						else if(arguments[i]==='log'){
							next.log=true;
						}
						else if(arguments[i]=='fromStorage'){
							next.fromStorage=true;
						}
						else if(arguments[i]=='fromRenku'){
							next.fromStorage=true;
							next.fromRenku=true;
						}
						else if(arguments[i]=='bySelf'){
							next.bySelf=true;
						}
						else if(typeof arguments[i]=='string'){
							next.animate=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.delay=arguments[i];
						}
					}
					if(next.animate=='gain2'||next.animate=='draw2'){
						if(!next.hasOwnProperty('log')){
							next.log=true;
						}
					}
					next.setContent('gain');
					next.getd=function(player,key,position){
						if(!position) position=ui.discardPile;
						if(!key) key='cards';
						var cards=[],event=this;
						game.checkGlobalHistory('cardMove',function(evt){
							if(evt.name!='lose'||evt.position!=position||evt.getParent()!=event) return;
							if(player&&player!=evt.player) return;
							cards.addArray(evt[key]);
						});
						return cards;
					};
					next.getl=function(player){
						const that=this;
						const map={
							player:player,
							hs:[],
							es:[],
							js:[],
							ss:[],
							xs:[],
							cards:[],
							cards2:[],
							gaintag_map:{},
						};
						player.checkHistory('lose',function(evt){
							if(evt.parent==that){
								map.hs.addArray(evt.hs);
								map.es.addArray(evt.es);
								map.js.addArray(evt.js);
								map.ss.addArray(evt.ss);
								map.xs.addArray(evt.xs);
								map.cards.addArray(evt.cards);
								map.cards2.addArray(evt.cards2);
								for(let key in evt.gaintag_map){
									if(!map.gaintag_map[key]) map.gaintag_map[key]=[];
									map.gaintag_map[key].addArray(evt.gaintag_map[key]);
								}
							}
						});
						return map;
					};
					next.getg=function(player){
						if(this.getlx===false||player!=this.player||!this.cards) return [];
						return this.cards.slice(0);
					}
					next.gaintag=[];
					return next;
				},
				addToExpansion:function(){
					var next=game.createEvent('addToExpansion');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.cards=[arguments[i]];
						}
						else if(arguments[i]==='log'){
							next.log=true;
						}
						else if(arguments[i]=='fromStorage'){
							next.fromStorage=true;
						}
						else if(arguments[i]=='fromRenku'){
							next.fromStorage=true;
							next.fromRenku=true;
						}
						else if(arguments[i]=='bySelf'){
							next.bySelf=true;
						}
						else if(typeof arguments[i]=='string'){
							next.animate=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.delay=arguments[i];
						}
					}
					if(next.animate=='gain2'||next.animate=='draw2'||next.animate=='give'){
						if(!next.hasOwnProperty('log')){
							next.log=true;
						}
					}
					next.setContent('addToExpansion');
					next.getd=function(player,key,position){
						if(!position) position=ui.discardPile;
						if(!key) key='cards';
						var cards=[],event=this;
						game.checkGlobalHistory('cardMove',function(evt){
							if(evt.name!='lose'||evt.position!=position||evt.getParent()!=event) return;
							if(player&&player!=evt.player) return;
							cards.addArray(evt[key]);
						});
						return cards;
					};
					next.getl=function(player){
						const that=this;
						const map={
							player:player,
							hs:[],
							es:[],
							js:[],
							ss:[],
							xs:[],
							cards:[],
							cards2:[],
							gaintag_map:{},
						};
						player.checkHistory('lose',function(evt){
							if(evt.parent==that){
								map.hs.addArray(evt.hs);
								map.es.addArray(evt.es);
								map.js.addArray(evt.js);
								map.ss.addArray(evt.ss);
								map.xs.addArray(evt.xs);
								map.cards.addArray(evt.cards);
								map.cards2.addArray(evt.cards2);
								for(let key in evt.gaintag_map){
									if(!map.gaintag_map[key]) map.gaintag_map[key]=[];
									map.gaintag_map[key].addArray(evt.gaintag_map[key]);
								}
							}
						});
						return map;
					};
					next.gaintag=[];
					return next;
				},
				give:function(cards,target,visible){
					var next=target.gain(cards,this);
					next.animate=visible?'give':'giveAuto';
					next.giver=this;
					return next;
				},
				lose:function(){
					var next=game.createEvent('lose');
					next.player=this;
					next.forceDie=true;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.cards=[arguments[i]];
						}
						else if(get.objtype(arguments[i])=='div'){
							next.position=arguments[i];
						}
						else if(arguments[i]=='toStorage'){
							next.toStorage=true;
						}
						else if(arguments[i]=='toRenku'){
							next.toStorage=true;
							next.toRenku=true;
						}
						else if(arguments[i]=='visible'){
							next.visible=true;
						}
						else if(arguments[i]=='insert'){
							next.insert_card=true;
						}
					}
					if(next.cards){
						var hej=this.getCards('hejsx');
						for(var i=0;i<next.cards.length;i++){
							if(!hej.contains(next.cards[i])){
								next.cards.splice(i--,1);
							}
						}
					}
					if(!next.cards||!next.cards.length){
						_status.event.next.remove(next);
					}
					else{
						if(next.position==undefined) next.position=ui.discardPile;
						next.cards=next.cards.slice(0);
					}
					next.setContent('lose');
					next.getd=function(player,key,position){
						if(!position) position=ui.discardPile;
						if(!key) key='cards';
						if(this.getlx===false||this.position!=position||(player&&this.player!=player)||!Array.isArray(this[key])) return [];
						return this[key].slice(0);
					};
					next.getl=function(player){
						if(this.getlx!==false&&this.player==player) return this;
						return {
							player:player,
							hs:[],
							es:[],
							js:[],
							ss:[],
							xs:[],
							cards:[],
							cards2:[],
							gaintag_map:{},
						};
					};
					return next;
				},
				damage:function(){
					var next=game.createEvent('damage');
					//next.forceDie=true;
					next.player=this;
					var nocard,nosource;
					var event=_status.event;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.num=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]&&arguments[i].name){
							next.card=arguments[i];
						}
						else if(arguments[i]=='nocard'){
							nocard=true;
						}
						else if(arguments[i]=='nosource'){
							nosource=true;
						}
						else if(arguments[i]=='notrigger'){
							next._triggered=null;
							next.notrigger=true;
						}
						else if(arguments[i]=='unreal'){
							next.unreal=true
						}
						else if(get.itemtype(arguments[i])=='nature'&&arguments[i]!='stab'){
							next.nature=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='natures'){
							var natures=arguments[i].split(lib.natureSeparator);
							natures.remove('stab');
							if(natures.length) next.nature=natures.join(lib.natureSeparator);
						}
					}
					if(next.card==undefined&&!nocard) next.card=event.card;
					if(next.cards==undefined&&!nocard) next.cards=event.cards;
					if(next.source==undefined&&!nosource) next.source=event.customSource||event.player;
					if(next.source&&next.source.isDead()) delete next.source;
					if(next.unreal==undefined) next.unreal=false;
					if(next.num==undefined) next.num=(event.baseDamage||1)+(event.extraDamage||0);
					next.original_num=next.num;
					next.change_history=[];
					next.hasNature=function(nature){
						if(!nature) return Boolean(this.nature&&this.nature.length>0);
						let natures=get.natureList(nature),naturesx=get.natureList(this.nature);
						if(nature=='linked') return naturesx.some(n=>lib.linked.includes(n));
						return get.is.sameNature(natures,naturesx);
					};
					if(next.hasNature('poison')) delete next._triggered;
					next.setContent('damage');
					next.filterStop=function(){
						if(this.source&&this.source.isDead()) delete this.source;
						var num=this.original_num;
						for(var i of this.change_history) num+=i;
						if(num!=this.num) this.change_history.push(this.num-num);
						if(this.num<=0){
							delete this.filterStop;
							this.trigger('damageZero');
							this.finish();
							this._triggered=null;
							return true;
						}
					};
					return next;
				},
				recover:function(){
					var next=game.createEvent('recover');
					next.player=this;
					var nocard,nosource;
					var event=_status.event;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='cards'){
							next.cards=arguments[i].slice(0);
						}
						else if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(get.itemtype(arguments[i])=='player'){
							next.source=arguments[i];
						}
						else if(typeof arguments[i]=='object'&&arguments[i]&&arguments[i].name){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='number'){
							next.num=arguments[i];
						}
						else if(arguments[i]=='nocard'){
							nocard=true;
						}
						else if(arguments[i]=='nosource'){
							nosource=true;
						}
					}
					if(next.card==undefined&&!nocard) next.card=event.card;
					if(next.cards==undefined&&!nocard) next.cards=event.cards;
					if(next.source==undefined&&!nosource) next.source=event.customSource||event.player;
					if(next.num==undefined) next.num=(event.baseDamage||1)+(event.extraDamage||0);
					if(next.num<=0) _status.event.next.remove(next);
					next.setContent('recover');
					return next;
				},
				doubleDraw:function(){
					if(get.is.changban()) return;
					var next=game.createEvent('doubleDraw');
					next.player=this;
					next.setContent('doubleDraw');
					return next;
				},
				loseHp:function(num){
					var next=game.createEvent('loseHp');
					next.num=num;
					next.player=this;
					if(next.num==undefined) next.num=1;
					next.setContent('loseHp');
					return next;
				},
				loseMaxHp:function(){
					var next=game.createEvent('loseMaxHp');
					next.player=this;
					next.num=1;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]==='number'){
							next.num=arguments[i];
						}
						else if(typeof arguments[i]==='boolean'){
							next.forced=arguments[i];
						}
					}
					next.setContent('loseMaxHp');
					return next;
				},
				gainMaxHp:function(){
					var next=game.createEvent('gainMaxHp');
					next.player=this;
					next.num=1;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]==='number'){
							next.num=arguments[i];
						}
						else if(typeof arguments[i]==='boolean'){
							next.forced=arguments[i];
						}
					}
					next.setContent('gainMaxHp');
					return next;
				},
				changeHp:function(num,popup){
					var next=game.createEvent('changeHp');
					next.num=num;
					if(popup!=undefined) next.popup=popup;
					next.player=this;
					next.setContent('changeHp');
					return next;
				},

				changeHujia:function(num,type,limit){
					var next=game.createEvent('changeHujia');
					if(typeof num!='number'){
						num=1;
					}
					next.num=num;
					next.player=this;
					if(type) next.type=type;
					next.setContent('changeHujia');
					if(limit===true) limit=5;
					if(typeof limit=='number'&&this.hujia+num>parseInt(limit)){
						var numx=parseInt(limit)-this.hujia;
						if(numx>0) next.num=numx;
						else _status.event.next.remove(next);
					}
					return next;
				},
				getBuff:function(){
					var list=[1,2,3,4,5,6];
					var nodelay=false;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							list.remove(arguments[i]);
						}
						else if(arguments[i]===false){
							nodelay=true;
						}
					}
					if(this.isHealthy()){
						list.remove(2);
					}
					if(!this.countCards('j')){
						list.remove(5);
					}
					if(!this.isLinked()&&!this.isTurnedOver()){
						list.remove(6);
					}
					if(this.hasSkill('qianxing')){
						list.remove(4);
					}
					switch(list.randomGet()){
						case 1:this.draw(nodelay?'nodelay':1);break;
						case 2:this.recover();break;
						case 3:this.changeHujia();break;
						case 4:this.tempHide();
						case 5:this.discard(this.getCards('j')).delay=(!nodelay);break;
						case 6:{
							if(this.isLinked()) this.link();
							if(this.isTurnedOver()) this.turnOver();
							break;
						}
					}
					return this;
				},
				getDebuff:function(){
					var list=[1,2,3,4,5,6];
					var nodelay=false;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='number'){
							list.remove(arguments[i]);
						}
						else if(arguments[i]===false){
							nodelay=true;
						}
					}
					if(this.countCards('he')==0){
						list.remove(1);
					}
					if(this.isLinked()){
						list.remove(4);
					}
					if(this.hasSkill('fengyin')){
						list.remove(5);
					}
					if(this.hp==1){
						list.remove(3);
						if(list.length>1) list.remove(2);
					}
					if(!list.length) return this;
					var num=list.randomGet();
					switch(list.randomGet()){
						case 1:this.randomDiscard(nodelay?false:'he');break;
						case 2:this.loseHp();break;
						case 3:this.damage();break;
						case 4:if(!this.isLinked()) this.link();break;
						case 5:this.addTempSkill('fengyin',{player:'phaseAfter'});break;
						case 6:{
							var list=[];
							for(var i=0;i<lib.inpile.length;i++){
								var info=lib.card[lib.inpile[i]];
								if(info.type=='delay'&&!info.cancel&&!this.hasJudge(lib.inpile[i])){
									list.push(lib.inpile[i]);
								}
							}
							if(list.length){
								var card=game.createCard(list.randomGet());
								this.addJudge(card);
								this.$draw(card);
								if(!nodelay) game.delay();
							}
							else{
								this.getDebuff(6);
							}
							break;
						}
					}
					return this;
				},
				dying:function(reason){
					if(this.nodying||this.hp>0||this.isDying()) return;
					var next=game.createEvent('dying');
					next.player=this;
					next.reason=reason;
					if(reason&&reason.source) next.source=reason.source;
					next.setContent('dying');
					next.filterStop=function(){
						if(this.player.hp>0||this.nodying){
							delete this.filterStop;
							return true;
						}
					};
					return next;
				},
				die:function(reason){
					var next=game.createEvent('die');
					next.player=this;
					next.reason=reason;
					if(reason) next.source=reason.source;
					next.setContent('die');
					return next;
				},
				revive:function(hp,log){
					if(log!==false) game.log(this,'复活');
					if(this.maxHp<1) this.maxHp=1;
					if(hp) this.hp=hp;
					else{
						this.hp=1;
					}
					game.addVideo('revive',this);
					this.classList.remove('dead');
					this.removeAttribute('style');
					this.node.avatar.style.transform='';
					this.node.avatar2.style.transform='';
					this.node.hp.show();
					this.node.equips.show();
					this.node.count.show();
					this.update();
					var player;
					player=this.previousSeat;
					while(player.isDead()) player=player.previousSeat;
					player.next=this;
					this.previous=player;
					player=this.nextSeat;
					while(player.isDead()) player=player.nextSeat;
					player.previous=this;
					this.next=player;
					game.players.add(this);
					game.dead.remove(this);
					if(this==game.me){
						if(ui.auto) ui.auto.show();
						if(ui.wuxie) ui.wuxie.show();
						if(ui.revive){
							ui.revive.close();
							delete ui.revive;
						}
						if(ui.exit){
							ui.exit.close();
							delete ui.exit;
						}
						if(ui.swap){
							ui.swap.close();
							delete ui.swap;
						}
						if(ui.restart){
							ui.restart.close();
							delete ui.restart;
						}
						if(ui.continue_game){
							ui.continue_game.close();
							delete ui.continue_game;
						}
					}
				},
				isMad:function(){
					return this.hasSkill('mad');
				},
				goMad:function(end){
					if(end){
						this.addTempSkill('mad',end);
					}
					else{
						this.addSkill('mad');
					}
					game.log(this,'进入混乱状态');
				},
				unMad:function(){
					this.removeSkill('mad');
				},
				tempHide:function(){
					this.addTempSkill('qianxing',{player:'phaseBegin'});
				},
				addExpose:function(num){
					if(typeof this.ai.shown=='number'&&!this.identityShown&&this.ai.shown<1){
						this.ai.shown+=num;
						if(this.ai.shown>0.95){
							this.ai.shown=0.95;
						}
					}
					return this;
				},
				equip:function(card,draw){
					var next=game.createEvent('equip');
					next.card=card;
					next.player=this;
					if(draw){
						next.draw=true;
					}
					next.setContent(lib.element.content.equip);
					if(get.is.object(next.card)&&next.card.cards) next.card=next.card.cards[0];
					next.cards=[next.card];
					next.getd=function(player,key,position){
						if(!position) position=ui.discardPile;
						if(!key) key='cards';
						var cards=[],event=this;
						game.checkGlobalHistory('cardMove',function(evt){
							if(evt.name!='lose'||evt.position!=position||evt.getParent()!=event) return;
							if(player&&player!=evt.player) return;
							cards.addArray(evt[key]);
						});
						return cards;
					};
					next.getl=function(player){
						const that=this;
						const map={
							player:player,
							hs:[],
							es:[],
							js:[],
							ss:[],
							xs:[],
							cards:[],
							cards2:[],
							gaintag_map:{},
						};
						player.checkHistory('lose',function(evt){
							if(evt.parent==that){
								map.hs.addArray(evt.hs);
								map.es.addArray(evt.es);
								map.js.addArray(evt.js);
								map.ss.addArray(evt.ss);
								map.xs.addArray(evt.xs);
								map.cards.addArray(evt.cards);
								map.cards2.addArray(evt.cards2);
								for(let key in evt.gaintag_map){
									if(!map.gaintag_map[key]) map.gaintag_map[key]=[];
									map.gaintag_map[key].addArray(evt.gaintag_map[key]);
								}
							}
						});
						return map;
					};
					return next;
				},
				addJudge:function(card,cards){
					var next=game.createEvent('addJudge');
					if(get.itemtype(card)=='card'){
						next.card=card;
						next.cards=[card];
					}
					else{
						next.cards=cards;
						if(get.itemtype(next.cards)=='card') next.cards=[next.cards];
						if(typeof card=='string'){
							card={name:card};
						}
						next.card=get.autoViewAs(card,next.cards)
					}
					next.player=this;
					next.setContent('addJudge');
					next.getd=function(player,key,position){
						if(!position) position=ui.discardPile;
						if(!key) key='cards';
						var cards=[],event=this;
						game.checkGlobalHistory('cardMove',function(evt){
							if(evt.name!='lose'||evt.position!=position||evt.getParent()!=event) return;
							if(player&&player!=evt.player) return;
							cards.addArray(evt[key]);
						});
						return cards;
					};
					next.getl=function(player){
						const that=this;
						const map={
							player:player,
							hs:[],
							es:[],
							js:[],
							ss:[],
							xs:[],
							cards:[],
							cards2:[],
							gaintag_map:{},
						};
						player.checkHistory('lose',function(evt){
							if(evt.parent==that){
								map.hs.addArray(evt.hs);
								map.es.addArray(evt.es);
								map.js.addArray(evt.js);
								map.ss.addArray(evt.ss);
								map.xs.addArray(evt.xs);
								map.cards.addArray(evt.cards);
								map.cards2.addArray(evt.cards2);
								for(let key in evt.gaintag_map){
									if(!map.gaintag_map[key]) map.gaintag_map[key]=[];
									map.gaintag_map[key].addArray(evt.gaintag_map[key]);
								}
							}
						});
						return map;
					};
					return next;
				},
				canAddJudge:function(card){
					if(this.isDisabledJudge()) return false;
					var name;
					if(typeof card=='string'){
						name=card;
					}
					else{
						name=card.viewAs||card.name;
					}
					if(!name) return false;
					if(this.hasJudge(name)) return false;
					if(this.isOut()) return false;
					var mod=game.checkMod(card,this,this,'unchanged','targetEnabled',this);
					if(mod!='unchanged') return mod;
					return true;
				},
				addJudgeNext:function(card,unlimited){
					if(!card.expired){
						let target=this.next;
						const name=card.viewAs||card.name;
						const cards=(get.itemtype(card)=='card')?[card]:card.cards;
						if(get.itemtype(cards)!='cards') return;
						let bool=false;
						if(!unlimited&&cards.some(card=>{
							const position=get.position(card,true);
							return position!='j'&&position!='o';
						})){
			  				game.log(card,'已被移出处理区,无法置入判定区');
							return;
						}
						for(let iwhile=0;iwhile<20;iwhile++){
							if(target.canAddJudge(card)){
								bool=true;break;
							}
							target=target.next;
						}
						if(bool){
							if(card.cards&&card.cards.length){
								target.addJudge(name,card.cards[0]);
							}
							else if(card.name!=name){
								target.addJudge(name,card);
							}
							else{
								target.addJudge(card);
							}
						}
					}
					else{
						card.expired=false;
					}
				},
				judge:function(){
					var next=game.createEvent('judge');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(get.itemtype(arguments[i])=='card'){
							next.card=arguments[i];
						}
						else if(typeof arguments[i]=='string'){
							next.skill=arguments[i];
						}
						else if(typeof arguments[i]=='function'){
							next.judge=arguments[i];
						}
						else if(typeof arguments[i]=='boolean'){
							next.clearArena=arguments[i];
						}
						else if(get.objtype(arguments[i])=='div'){
							next.position=arguments[i];
						}
					}
					if(next.card&&next.judge==undefined){
						next.judge=get.judge(next.card);
						next.judge2=get.judge2(next.card);
					}
					if(next.judge==undefined) next.judge=function(){return 0};
					if(next.position==undefined) next.position=ui.discardPile;
					if(next.card) next.cardname=next.card.viewAs||next.card.name;

					var str='';
					if(next.card) str=get.translation(next.card.viewAs||next.card.name);
					else if(next.skill) str=get.translation(next.skill);
					else str=get.translation(_status.event.name);
					next.judgestr=str;
					next.setContent('judge');
					return next;
				},
				turnOver:function(bool){
					if(typeof bool=='boolean'){
						if(bool){
							if(this.isTurnedOver()) return;
						}
						else{
							if(!this.isTurnedOver()) return;
						}
					}
					var next=game.createEvent('turnOver');
					next.player=this;
					next.includeOut=true;
					next.setContent('turnOver');
					return next;
				},
				out:function(skill){
					if(typeof skill=='number'){
						this.outCount+=skill;
					}
					else if(typeof skill=='string'){
						if(!this.outSkills){
							this.outSkills=[];
						}
						this.outSkills.add(skill);
					}
					else{
						this.outCount++;
					}
					if(!this.classList.contains('out')){
						this.classList.add('out');
						game.log(this,'离开游戏');
					}
					if(!game.countPlayer()){
						game.over();
					}
				},
				in:function(skill){
					if(this.isOut()){
						if(typeof skill=='string'){
							if(this.outSkills){
								this.outSkills.remove(skill);
								if(!this.outSkills.length){
									delete this.outSkills;
								}
							}
						}
						else if(typeof skill=='number'){
							this.outCount-=skill;
						}
						else{
							if(skill===true){
								delete this.outSkills;
							}
							this.outCount=0;
						}
						if(this.outCount<=0&&!this.outSkills){
							this.outCount=0;
							this.classList.remove('out');
							game.log(this,'进入游戏');
						}
					}
				},
				link:function(bool){
					if(typeof bool=='boolean'){
						if(bool){
							if(this.isLinked()) return;
						}
						else{
							if(!this.isLinked()) return;
						}
					}
					var next=game.createEvent('link');
					next.player=this;
					next.setContent('link');
					return next;
				},
				skip:function(name){
					this.skipList.add(name);
				},
				wait:function(callback){
					if(lib.node){
						if(typeof callback=='function'){
							callback._noname_waiting=true;
							lib.node.torespond[this.playerid]=callback;
						}
						else{
							lib.node.torespond[this.playerid]='_noname_waiting';
						}
						clearTimeout(lib.node.torespondtimeout[this.playerid]);
						if(this.ws&&!this.ws.closed){
							var player=this;
							var time=parseInt(lib.configOL.choose_timeout)*1000;
							if(_status.event._global_timer||_status.event.getParent().skillHidden){
								for(var i=0;i<game.players.length;i++){
									game.players[i].showTimer(time);
								}
								player._hide_all_timer=true;
							}
							else if(!_status.event._global_waiting){
								player.showTimer(time);
							}
							lib.node.torespondtimeout[this.playerid]=setTimeout(function(){
								player.unwait('ai');
								player.ws.ws.close();
							},time+5000);
						}
					}
				},
				unwait:function(result){
					if(this._hide_all_timer){
						delete this._hide_all_timer;
						for(var i=0;i<game.players.length;i++){
							game.players[i].hideTimer();
						}
					}
					else if(!_status.event._global_waiting){
						this.hideTimer();
					}
					clearTimeout(lib.node.torespondtimeout[this.playerid]);
					delete lib.node.torespondtimeout[this.playerid];
					if(!lib.node.torespond.hasOwnProperty(this.playerid)){
						return;
					}
					var noresume=false;
					var proceed=null;
					if(typeof lib.node.torespond[this.playerid]=='function'&&lib.node.torespond[this.playerid]._noname_waiting){
						proceed=lib.node.torespond[this.playerid](result,this);
						if(proceed===false){
							noresume=true;
						}
					}
					lib.node.torespond[this.playerid]=result;
					for(var i in lib.node.torespond){
						if(lib.node.torespond[i]=='_noname_waiting'){
							return;
						}
						else if(lib.node.torespond[i]&&lib.node.torespond[i]._noname_waiting){
							return;
						}
					}
					_status.event.result=result;
					_status.event.resultOL=lib.node.torespond;
					lib.node.torespond={};
					if(typeof proceed=='function') proceed();
					else if(_status.paused&&!noresume) game.resume();
				},
				tempUnwait:function(result){
					if(!lib.node.torespond.hasOwnProperty(this.playerid)){
						return;
					}
					var proceed;
					if(typeof lib.node.torespond[this.playerid]=='function'&&lib.node.torespond[this.playerid]._noname_waiting){
						proceed=lib.node.torespond[this.playerid](result,this);
					}
					if(typeof proceed=='function') proceed();
				},
				logSkill:function(name,targets,nature,logv){
					if(get.itemtype(targets)=='player') targets=[targets];
					var nopop=false;
					var popname=name;
					if(Array.isArray(name)){
						popname=name[1];
						name=name[0];
					}
					var checkShow=this.checkShow(name);
					if(lib.translate[name]){
						this.trySkillAnimate(name,popname,checkShow);
						if(Array.isArray(targets)&&targets.length){
							var str;
							if(targets[0]==this){
								str='#b自己';
								if(targets.length>1){
									str+='、';
									str+=get.translation(targets.slice(1));
								}
							}
							else str=targets;
							game.log(this,'对',str,'发动了','【'+get.skillTranslation(name,this)+'】');
						}
						else{
							game.log(this,'发动了','【'+get.skillTranslation(name,this)+'】');
						}
					}
					if(nature!=false){
						if(nature===undefined){
							nature='green';
						}
						this.line(targets,nature);
					}
					var info=lib.skill[name];
					if(info&&info.ai&&info.ai.expose!=undefined&&
						this.logAi&&(!targets||targets.length!=1||targets[0]!=this)){
						this.logAi(lib.skill[name].ai.expose);
					}
					if(info&&info.round){
						var roundname=name+'_roundcount';
						this.storage[roundname]=game.roundNumber;
						this.syncStorage(roundname);
						this.markSkill(roundname);
					}
					game.trySkillAudio(name,this,true);
					if(game.chess){
						this.chessFocus();
					}
					if(logv===true){
						game.logv(this,name,targets,null,true);
					}
					else if(info&&info.logv!==false){
						game.logv(this,name,targets);
					}
					if(info){
						var player=this;
						var players=player.getSkills(false,false,false);
						var equips=player.getSkills('e');
						var global=lib.skill.global.slice(0);
						var logInfo={
							skill:name,
							targets:targets,
							event:_status.event,
						};
						if(info.sourceSkill){
							logInfo.sourceSkill=info.sourceSkill;
							if(global.contains(info.sourceSkill)){
								logInfo.type='global';
							}
							else if(players.contains(info.sourceSkill)){
								logInfo.type='player';
							}
							else if(equips.contains(info.sourceSkill)){
								logInfo.type='equip';
							}
						}
						else{
							if(global.contains(name)){
								logInfo.sourceSkill=name;
								logInfo.type='global';
							}
							else if(players.contains(name)){
								logInfo.sourceSkill=name;
								logInfo.type='player';
							}
							else if(equips.contains(name)){
								logInfo.sourceSkill=name;
								logInfo.type='equip';
							}
							else{
								var bool=false;
								for(var i of players){
									var expand=[i];
									game.expandSkills(expand);
									if(expand.contains(name)){
										bool=true;
										logInfo.sourceSkill=i;
										logInfo.type='player';
										break;
									}
								}
								if(!bool){
									for(var i of players){
										var expand=[i];
										game.expandSkills(expand);
										if(expand.contains(name)){
											logInfo.sourceSkill=i;
											logInfo.type='equip';
											break;
										}
									}
								}
							}
						}
						var next=game.createEvent('logSkill',false),evt=_status.event;
						next.player=player;
						next.forceDie=true;
						next.includeOut=true;
						evt.next.remove(next);
						if(evt.logSkill) evt=evt.getParent();
						for(var i in logInfo){
							if(i=='event') next.log_event=logInfo[i];
							else next[i]=logInfo[i];
						}
						evt.after.push(next);
						next.setContent('emptyEvent');
						player.getHistory('useSkill').push(logInfo);
						//尽可能别往这写插入结算
						//不能用来终止技能发动!!!
						var next2=game.createEvent('logSkillBegin',false);
						next2.player=player;
						next2.forceDie=true;
						next2.includeOut=true;
						for(var i in logInfo){
							if(i=='event') next2.log_event=logInfo[i];
							else next2[i]=logInfo[i];
						}
						next2.setContent('emptyEvent');
					}
					if(this._hookTrigger){
						for(var i=0;i<this._hookTrigger.length;i++){
							var info=lib.skill[this._hookTrigger[i]].hookTrigger;
							if(info&&info.log){
								info.log(this,name,targets);
							}
						}
					}
				},
				unprompt:function(){
					if(this.node.prompt){
						this.node.prompt.delete();
						delete this.node.prompt;
					}
				},
				prompt:function(str,nature){
					var node;
					if(this.node.prompt){
						node=this.node.prompt;
						node.innerHTML='';
						node.className='damage normal-font damageadded';
					}
					else{
						node=ui.create.div('.damage.normal-font',this);
						this.node.prompt=node;
						ui.refresh(node);
						node.classList.add('damageadded');
					}
					node.innerHTML=str;
					node.dataset.nature=nature||'soil';
				},
				prompt_old:function(name2,className){
					var node;
					if(this.node.prompt){
						node=this.node.prompt;
						node.innerHTML='';
						node.className='popup';
					}
					else{
						node=ui.create.div('.popup',this.parentNode);
						this.node.prompt=node;
					}
					node.dataset.position=this.dataset.position;
					if(this.dataset.position==0||parseInt(this.dataset.position)==parseInt(ui.arena.dataset.number)/2||
						typeof name2=='number'||this.classList.contains('minskin')){
						node.innerHTML=name2;
					}
					else{
						for(var i=0;i<name2.length;i++){
							node.innerHTML+=name2[i]+'<br/>';
						}
					}
					if(className){
						node.classList.add(className);
					}
				},
				popup:function(name,className,nobroadcast){
					var name2=get.translation(name);
					if(!name2) return;
					this.$damagepop(name2,className||'water',true,nobroadcast);
				},
				popup_old:function(name,className){
					var name2=get.translation(name);
					var node=ui.create.div('.popup',this.parentNode);
					if(!name2){
						node.remove();
						return node;
					}
					game.addVideo('popup',this,[name,className]);
					node.dataset.position=this.dataset.position;
					if(this.dataset.position==0||parseInt(this.dataset.position)==parseInt(ui.arena.dataset.number)/2||
						typeof name2=='number'||this.classList.contains('minskin')){
						node.innerHTML=name2;
					}
					else{
						for(var i=0;i<name2.length;i++){
							node.innerHTML+=name2[i]+'<br/>';
						}
					}
					if(className){
						node.classList.add(className);
					}
					this.popups.push(node);
					if(this.popups.length>1){
						node.hide();
					}
					else{
						var that=this;
						setTimeout(function(){that._popup();},1000);
					}
					return node;
				},
				_popup:function(){
					if(this.popups.length){
						this.popups.shift().delete();
						if(this.popups.length){
							this.popups[0].show();
							var that=this;
							setTimeout(function(){that._popup();},1000);
						}
					}
				},
				showTimer:function(time){
					if(!time&&lib.configOL){
						time=parseInt(lib.configOL.choose_timeout)*1000;
					}
					if(_status.connectMode&&!game.online){
						game.broadcast(function(player,time){
							player.showTimer(time);
						},this,time);
					}
					if(this==game.me){
						return;
					}
					if(this.node.timer){
						this.node.timer.remove();
					}
					var timer=ui.create.div('.timerbar',this);
					this.node.timer=timer;
					ui.create.div(this.node.timer);
					var bar=ui.create.div(this.node.timer);
					ui.refresh(bar);
					bar.style.transitionDuration=(time/1000)+'s';
					bar.style.transform='scale(0,1)';
				},
				hideTimer:function(){
					if(_status.connectMode&&!game.online&&this.playerid){
						game.broadcast(function(player){
							player.hideTimer();
						},this);
					}
					if(this.node.timer){
						this.node.timer.delete();
						delete this.node.timer;
					}
				},
				markAuto:function(name,info){
					if(typeof info!='undefined'){
						if(!Array.isArray(this.storage[name])) this.storage[name]=[];
						if(Array.isArray(info)){
							this.storage[name].addArray(info);
						}
						else this.storage[name].add(info);
						this.markSkill(name);
					}
					else{
						var storage=this.storage[name];
						if(Array.isArray(storage)){
							this[storage.length>0?'markSkill':'unmarkSkill'](name);
						}
						else if(typeof storage=='number'){
							this[storage>0?'markSkill':'unmarkSkill'](name);
						}
					}
				},
				unmarkAuto:function(name,info){
					var storage=this.storage[name]
					if(Array.isArray(info)&&Array.isArray(storage)){
						storage.removeArray(info.slice(0));
						this.markAuto(name);
					}
				},
				getExpansions:function(tag){
					return this.getCards('x',(card)=>card.hasGaintag(tag));
				},
				countExpansions:function(tag){
					return this.getExpansions(tag).length;
				},
				hasExpansions:function(tag){
					return this.countExpansions(tag)>0;
				},
				setStorage:function(name,value,mark){
					this.storage[name]=value;
					if(mark) this.markAuto(name);
					return value;
				},
				getStorage:function(name){
					return this.storage[name]||[];
				},
				hasStorage:function(name,value){
					if(!(name in this.storage)) return false;
					if(typeof value=="undefined") return true;
					const storage=this.storage[name];
					if(storage===value) return true;
					return Array.isArray(storage) && storage.includes(value);
				},
				hasStorageAny:function(name,values){
					const storage=this.storage[name];
					if(!Array.isArray(values)) values=Array.from(arguments).slice(1);
					if(!storage) return false;
					if (!Array.isArray(storage)) return values.contains(storage);
					return values.some(item => storage.contains(item));
				},
				hasStorageAll:function(name,values){
					const storage=this.storage[name];
					if(!Array.isArray(values)) values=Array.from(arguments).slice(1);
					if(!storage) return false;
					if (!Array.isArray(storage)) return false;
					return values.every(item => storage.contains(item));
				},
				initStorage:function(name,value,mark){
					return this.hasStorage(name)?this.getStorage(name):this.setStorage(name,value,mark);
				},
				updateStorage:function(name,operation,mark){
					return this.setStorage(name,operation(this.getStorage(name)),mark);
				},
				updateStorageAsync:function(name,operation,mark){
					return Promise.resolve(this.getStorage(name))
					.then(value=>operation(value))
					.then(value=>this.setStorage(name,value,mark));
				},
				removeStorage:function(name,mark){
					if(!this.hasStorage(name)) return false;
					delete this.storage[name]
					if(mark){
						this.unmarkSkill(name);
					}
					return true;
				},
				markSkill:function(name,info,card,nobroadcast){
					if(info===true){
						this.syncStorage(name);
						info=null;
					}
					if(get.itemtype(card)=='card'){
						game.addVideo('markSkill',this,[name,get.cardInfo(card)]);
					}
					else{
						game.addVideo('markSkill',this,[name]);
					}
					const func=function(storage,player,name,info,card){
						player.storage[name]=storage;
						if(!info){
							if(player.marks[name]){
								player.updateMarks();
								return;
							}
							if(lib.skill[name]){
								info=lib.skill[name].intro;
							}
							if(!info){
								return;
							}
						}
						if(player.marks[name]){
							player.marks[name].info=info;
						}
						else{
							if(card){
								player.marks[name]=player.mark(card,info,name);
							}
							else{
								player.marks[name]=player.mark(name,info);
							}
						}
						player.updateMarks();
					};
					func(this.storage[name],this,name,info,card);
					if(!nobroadcast) game.broadcast(func,this.storage[name],this,name,info,card);
					return this;
				},
				unmarkSkill:function(name,nobroadcast){
					game.addVideo('unmarkSkill',this,name);
					if(!nobroadcast) game.broadcast(function(player,name){
						if(player.marks[name]){
							player.marks[name].delete();
							player.marks[name].style.transform+=' scale(0.2)';
							delete player.marks[name];
							ui.updatem(player);
						}
					},this,name);
					if(this.marks[name]){
						this.marks[name].delete();
						this.marks[name].style.transform+=' scale(0.2)';
						delete this.marks[name];
						ui.updatem(this);
						var info=lib.skill[name];
						if(!game.online&&info&&info.intro&&info.intro.onunmark){
							if(info.intro.onunmark=='throw'){
								if(get.itemtype(this.storage[name])=='cards'){
									this.$throw(this.storage[name],1000);
									game.cardsDiscard(this.storage[name]);
									game.log(this.storage[name],'进入了弃牌堆');
									this.storage[name].length=0;
								}
							}
							else if(typeof info.intro.onunmark=='function'){
								info.intro.onunmark(this.storage[name],this);
							}
							else delete this.storage[name];
						}
					}
					return this;
				},
				markSkillCharacter:function(id,target,name,content,nobroadcast){
					if(typeof target=='object'){
						target=target.name;
					}
					const func=function(player,target,name,content,id){
						if(player.marks[id]){
							player.marks[id].name=name+'_charactermark';
							player.marks[id]._name=target;
							player.marks[id].info={
								name:name,
								content:content,
								id:id
							};
							player.marks[id].setBackground(target,'character');
							game.addVideo('changeMarkCharacter',player,{
								id:id,
								name:name,
								content:content,
								target:target
							});
						}
						else{
							player.marks[id]=player.markCharacter(target,{
								name:name,
								content:content,
								id:id
							});
							player.marks[id]._name=target;
							game.addVideo('markCharacter',player,{
								name:name,
								content:content,
								id:id,
								target:target
							});
						}
					}
					func(this,target,name,content,id);
					if(!nobroadcast) game.broadcast(func,this,target,name,content,id);
					return this;
				},
				markCharacter:function(name,info,learn,learn2){
					if(typeof name=='object'){
						name=name.name;
					}
					var node;
					if(name.startsWith('unknown')){
						node=ui.create.div('.card.mark.drawinghidden');
						ui.create.div('.background.skillmark',node).innerHTML=get.translation(name)[0];
					}
					else{
						if(!lib.character[name]) return;
						node=ui.create.div('.card.mark.drawinghidden').setBackground(name,'character');
					}
					this.node.marks.insertBefore(node,this.node.marks.childNodes[1]);
					node.name=name+'_charactermark';
					if(!info){
						info={};
					}
					if(!info.name){
						info.name=get.translation(name);
					}
					if(!info.content){
						info.content=get.skillintro(name,learn,learn2)
					}
					node.info=info;
					node.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.card);
					if(!lib.config.touchscreen){
						if(lib.config.hover_all){
							lib.setHover(node,ui.click.hoverplayer);
						}
						if(lib.config.right_info){
							node.oncontextmenu=ui.click.rightplayer;
						}
					}
					ui.updatem(this);
					return node;
				},
				mark:function(name,info,skill){
					if(get.itemtype(name)=='cards'){
						var marks=[];
						for(var i=0;i<name.length;i++){
							marks.push(this.mark(name[i],info));
						}
						return marks;
					}
					else{
						var node;
						if(get.itemtype(name)=='card'){
							node=name.copy('mark');
							node.classList.add('drawinghidden');
							this.node.marks.insertBefore(node,this.node.marks.childNodes[1]);
							node.suit=name.suit;
							node.number=name.number;
							// if(name.name&&lib.card[name.name]&&lib.card[name.name].markimage){
							// 	node.node.image.style.left=lib.card[name.name].markimage;
							// }

							if(name.classList.contains('fullborder')){
								node.classList.add('fakejudge');
								node.classList.add('fakemark');
								(node.querySelector('.background')||ui.create.div('.background',node)).innerHTML=lib.translate[name.name+'_bg']||get.translation(name.name)[0];
							}

							name=name.name;
						}
						else{
							node=ui.create.div('.card.mark.drawinghidden');
							this.node.marks.insertBefore(node,this.node.marks.childNodes[1]);
							if(lib.skill[name]&&lib.skill[name].markimage){
								node.setBackgroundImage(lib.skill[name].markimage);
								node.style['box-shadow']='none';
								node.style['background-size']='contain';
							}
							else if(lib.skill[name]&&lib.skill[name].markimage2){
								let img=ui.create.div('.background.skillmark',node);
								img.setBackgroundImage(lib.skill[name].markimage2);
								img.style['background-size']='contain';
							}
							else{
								var str=lib.translate[name+'_bg'];
								if(!str||str[0]=='+'||str[0]=='-'){
									str=get.translation(name)[0];
								}
								ui.create.div('.background.skillmark',node).innerHTML=str;
							}
						}
						node.name=name;
						node.skill=skill||name;
						if(typeof info=='object'){
							node.info=info;
						}
						else if(typeof info=='string'){
							node.markidentifer=info;
						}
						node.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.card);
						if(!lib.config.touchscreen){
							if(lib.config.hover_all){
								lib.setHover(node,ui.click.hoverplayer);
							}
							if(lib.config.right_info){
								node.oncontextmenu=ui.click.rightplayer;
							}
						}
						this.updateMarks();
						ui.updatem(this);
						return node;
					}
				},
				unmark:function(name,info){
					game.addVideo('unmarkname',this,name);
					if(get.itemtype(name)=='card'){
						this.unmark(name.name,info);
					}
					else if(get.itemtype(name)=='cards'){
						for(var i=0;i<name.length;i++){
							this.unmark(name[i].name,info);
						}
					}
					else{
						for(var i=0;i<this.node.marks.childNodes.length;i++){
							if(this.node.marks.childNodes[i].name==name&&
								(!info||this.node.marks.childNodes[i].markidentifer==info)){
								this.node.marks.childNodes[i].delete();
								this.node.marks.childNodes[i].style.transform+=' scale(0.2)';
								ui.updatem(this);
								return;
							}
						}
					}
				},
				addLink:function(){
					if(get.is.linked2(this)){
						this.classList.add('linked2');
					}
					else{
						this.classList.add('linked');
					}
				},
				removeLink:function(){
					if(get.is.linked2(this)){
						this.classList.remove('linked2');
					}
					else{
						this.classList.remove('linked');
					}
				},
				canUse:function(card,target,distance,includecard){
					if(typeof card=='string') card={name:card,isCard:true};
					var info=get.info(card);
					if(info.multicheck&&!info.multicheck(card,this)) return false;
					if(!lib.filter.cardEnabled(card,this)) return false;
					if(includecard&&!lib.filter.cardUsable(card,this)) return false;
					if(distance!==false&&!lib.filter.targetInRange(card,this,target)) return false;
					return lib.filter[includecard?'targetEnabledx':'targetEnabled'](card,this,target);
				},
				hasUseTarget:function(card,distance,includecard){
					var player=this;
					return game.hasPlayer(function(current){
						return player.canUse(card,current,distance,includecard);
					});
				},
				hasValueTarget:function(){
					return this.getUseValue.apply(this,arguments)>0;
				},
				getUseValue:function(card,distance,includecard){
					if(typeof(card)=='string'){
						card={name:card,isCard:true};
					}
					var player=this;
					var targets=game.filterPlayer();
					var value=[];
					var min=0;
					var info=get.info(card);
					if(!info||info.notarget) return 0;
					var range;
					var select=get.copy(info.selectTarget);
					if(select==undefined){
						if(info.filterTarget==undefined) return true;
						range=[1,1];
					}
					else if(typeof select=='number') range=[select,select];
					else if(get.itemtype(select)=='select') range=select;
					else if(typeof select=='function') range=select(card,player);
					if(info.singleCard) range=[1,1];
					game.checkMod(card,player,range,'selectTarget',player);
					if(!range) return 0;
				
					for(var i=0;i<targets.length;i++){
						if(player.canUse(card,targets[i],distance,includecard)){
							var eff=get.effect(targets[i],card,player,player);
							value.push(eff);
						}
					}
					value.sort(function(a,b){
						return b-a;
					});
					for(var i=0;i<value.length;i++){
						if(i==range[1]||range[1]!=-1&&value[i]<=0) break;
						min+=value[i];
					}
					return min;
				},
				addSubPlayer:function(cfg){
					var skill='subplayer_'+cfg.name+'_'+get.id();
					game.log(this,'获得了随从','#g'+get.translation(cfg.name))
					cfg.hs=cfg.hs||[];
					cfg.es=cfg.es||[];
					cfg.skills=cfg.skills||[];
					cfg.hp=cfg.hp||1;
					cfg.maxHp=cfg.maxHp||1;
					cfg.sex=cfg.sex||'male';
					cfg.group=cfg.group||'qun';
					cfg.skill=cfg.skill||_status.event.name;
					if(!cfg.source){
						if(this.hasSkill(_status.event.name)&&this.name2&&lib.character[this.name2]&&
							lib.character[this.name2][3].contains(_status.event.name)){
							cfg.source=this.name2;
						}
						else{
							cfg.source=this.name;
						}
					}
					game.broadcastAll(function(player,skill,cfg){
						lib.skill[skill]={
							intro:{
								content:cfg.intro||''
							},
							mark:'character',
							subplayer:cfg.skill,
							ai:{
								subplayer:true
							}
						}
						lib.character[skill]=[cfg.sex,cfg.group,cfg.maxHp,cfg.skills,['character:'+cfg.name]];
						lib.translate[skill]=cfg.caption||get.rawName(cfg.name);
						player.storage[skill]=cfg;
					},this,skill,cfg);
					game.addVideo('addSubPlayer',this,[skill,lib.skill[skill],lib.character[skill],lib.translate[skill],{name:cfg.name}]);
					this.addSkill(skill);
					return skill;
				},
				removeSubPlayer:function(name){
					if(this.hasSkill('subplayer')&&this.name==name){
						this.exitSubPlayer(true);
					}
					else{
						if(player.storage[name].onremove){
							player.storage[name].onremove(player);
						}
						this.removeSkill(name);
						delete this.storage[name];
						game.log(player,'牺牲了随从','#g'+name);
						_status.event.trigger('removeSubPlayer');
					}
				},
				callSubPlayer:function(){
					if(this.hasSkill('subplayer')) return;
					var next=game.createEvent('callSubPlayer');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='string'){
							next.directresult=arguments[i];
						}
					}
					next.setContent('callSubPlayer');
					return next;
				},
				toggleSubPlayer:function(){
					if(!this.hasSkill('subplayer')) return;
					var next=game.createEvent('toggleSubPlayer');
					next.player=this;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='string'){
							next.directresult=arguments[i];
						}
					}
					next.setContent('toggleSubPlayer');
					return next;
				},
				exitSubPlayer:function(remove){
					if(!this.hasSkill('subplayer')) return;
					var next=game.createEvent('exitSubPlayer');
					next.player=this;
					next.remove=remove;
					next.setContent('exitSubPlayer');
					return next;
				},
				getSubPlayers:function(tag){
					var skills=this.getSkills();
					var list=[];
					for(var i=0;i<skills.length;i++){
						var name=skills[i];
						var info=lib.skill[name];
						if(tag&&info.subplayer!=tag) continue;
						if(info.ai&&info.ai.subplayer&&this.storage[name]&&this.storage[name].name){
							list.push(name);
						}
					}
					return list;
				},
				addSkillTrigger:function(skill,hidden,triggeronly){
					var info=lib.skill[skill];
					if(!info) return;
					if(typeof info.group=='string'){
						this.addSkillTrigger(info.group,hidden);
					}
					else if(Array.isArray(info.group)){
						for(var i=0;i<info.group.length;i++){
							this.addSkillTrigger(info.group[i],hidden);
						}
					}
					if(!triggeronly){
						if(info.global&&(!hidden||info.globalSilent)){
							if(typeof info.global=='string'){
								game.addGlobalSkill(info.global,this);
							}
							else{
								for(var j=0;j<info.global.length;j++){
									game.addGlobalSkill(info.global[j],this);
								}
							}
						}
						if(this.initedSkills.contains(skill)) return this;
						this.initedSkills.push(skill);
						if(info.init&&!_status.video){
							info.init(this,skill);
						}
					}
					if(info.trigger&&this.playerid){
						var playerid=this.playerid;
						var setTrigger=function(i,evt){
							if(i=='global'){
								if(!lib.hook.globaltrigger[evt]){
									lib.hook.globaltrigger[evt]={};
								}
								if(!lib.hook.globaltrigger[evt][playerid]){
									lib.hook.globaltrigger[evt][playerid]=[];
								}
								lib.hook.globaltrigger[evt][playerid].add(skill);
							}
							else{
								var name=playerid+'_'+i+'_'+evt;
								if(!lib.hook[name]){
									lib.hook[name]=[];
								}
								lib.hook[name].add(skill);
							}
							lib.hookmap[evt]=true;
						}
						for(var i in info.trigger){
							if(typeof info.trigger[i]=='string'){
								setTrigger(i,info.trigger[i]);
							}
							else if(Array.isArray(info.trigger[i])){
								for(var j=0;j<info.trigger[i].length;j++){
									setTrigger(i,info.trigger[i][j]);
								}
							}
						}
					}
					if(info.hookTrigger){
						if(!this._hookTrigger){
							this._hookTrigger=[];
						}
						this._hookTrigger.add(skill);
					}
					if(_status.event&&_status.event.addTrigger) _status.event.addTrigger(skill,this);
					return this;
				},
				addSkillLog:function(skill){
					this.addSkill(skill);
					this.popup(skill);
					game.log(this,'获得了技能','#g【'+get.translation(skill)+'】');
				},
				addInvisibleSkill:function(skill){
					if(Array.isArray(skill)){
						_status.event.clearStepCache();
						for(var i=0;i<skill.length;i++){
							this.addInvisibleSkill(skill[i]);
						}
					}
					else{
						if(this.invisibleSkills.contains(skill)) return;
						_status.event.clearStepCache();
						var info=lib.skill[skill];
						if(!info) return;
						this.invisibleSkills.add(skill);
						this.addSkillTrigger(skill);
						if(this.awakenedSkills.contains(skill)){
							this.awakenSkill(skill);
							return;
						}
					}
				},
				removeInvisibleSkill:function(skill){
					if(!skill) return;
					if(Array.isArray(skill)){
						for(var i=0;i<skill.length;i++){
							this.removeSkill(skill[i]);
						}
					}
					else{
						var info=lib.skill[skill];
						if(info&&info.fixed&&arguments[1]!==true) return skill;
						game.broadcastAll(function(player,skill){
							player.invisibleSkills.remove(skill);
						},this,skill);
						if(!player.hasSkill(skill,true)) player.removeSkill(skill);
					}
					return skill;
				},
				addSkill:function(skill,checkConflict,nobroadcast,addToSkills){
					if(Array.isArray(skill)){
						_status.event.clearStepCache();
						for(var i=0;i<skill.length;i++){
							this.addSkill(skill[i]);
						}
					}
					else{
						if(this.skills.contains(skill)) return;
						_status.event.clearStepCache();
						var info=lib.skill[skill];
						if(!info) return;
						if(!addToSkills){
							this.skills.add(skill);
							if(!nobroadcast){
								game.broadcast(function(player,skill){
									player.skills.add(skill);
								},this,skill);
							}
						}
						this.addSkillTrigger(skill);
						if(this.awakenedSkills.contains(skill)){
							this.awakenSkill(skill);
							return;
						}
						if(info.init2&&!_status.video){
							info.init2(this,skill);
						}
						if(info.mark){
							if(info.mark=='card'&&
								get.itemtype(this.storage[skill])=='card'){
									this.markSkill(skill,null,this.storage[skill],nobroadcast);
							}
							else if(info.mark=='card'&&
								get.itemtype(this.storage[skill])=='cards'){
									this.markSkill(skill,null,this.storage[skill][0],nobroadcast);
							}
							else if(info.mark=='image'){
									this.markSkill(skill,null,ui.create.card(null,'noclick').init([null,null,skill]),nobroadcast);
							}
							else if(info.mark=='character'){
								var intro=info.intro.content;
								if(typeof intro=='function'){
									intro=intro(this.storage[skill],this);
								}
								else if(typeof intro=='string'){
									intro=intro.replace(/#/g,this.storage[skill]);
									intro=intro.replace(/&/g,get.cnNumber(this.storage[skill]));
									intro=intro.replace(/\$/g,get.translation(this.storage[skill]));
								}
								var caption;
								if(typeof info.intro.name=='function'){
									caption=info.intro.name(this.storage[skill],this);
								}
								else if(typeof info.intro.name=='string'){
									caption=info.name;
								}
								else{
									caption=get.translation(skill);
								}
								this.markSkillCharacter(skill,this.storage[skill],caption,intro,nobroadcast);
							}
							else{
								this.markSkill(skill,null,null,nobroadcast);
							}
						}
					}
					if(checkConflict) this.checkConflict();
					return skill;
				},
				addAdditionalSkill:function(skill,skills,keep){
					if(this.additionalSkills[skill]){
						if(keep){
							if(typeof this.additionalSkills[skill]=='string'){
								this.additionalSkills[skill]=[this.additionalSkills[skill]];
							}
						}
						else{
							this.removeAdditionalSkill(skill);
							this.additionalSkills[skill]=[];
						}
					}
					else{
						this.additionalSkills[skill]=[];
					}
					if(typeof skills=='string'){
						skills=[skills];
					}
					for(var i=0;i<skills.length;i++){
						this.addSkill(skills[i],null,true,true);
						//this.skills.remove(skills[i]);
						this.additionalSkills[skill].push(skills[i]);
					}
					this.checkConflict();
					_status.event.clearStepCache();
					return this;
				},
				removeAdditionalSkill:function(skill,target){
					if(this.additionalSkills[skill]){
						var additionalSkills=this.additionalSkills[skill];
						if(Array.isArray(additionalSkills)&&typeof target=='string'){
							if(additionalSkills.contains(target)){
								additionalSkills.remove(target);
								if(!this.skills.contains(target)&&!this.tempSkills[target]) this.removeSkill(target);
							}
						}
						else{
							delete this.additionalSkills[skill];
							if(typeof additionalSkills=='string'){
								if(!this.skills.contains(additionalSkills)&&!this.tempSkills[additionalSkills]) this.removeSkill(additionalSkills);
							}
							else if(Array.isArray(additionalSkills)){
								for(var i=0;i<additionalSkills.length;i++){
									if(!this.skills.contains(additionalSkills[i])&&!this.tempSkills[additionalSkills[i]]) this.removeSkill(additionalSkills[i]);
								}
							}
						}
					}
					_status.event.clearStepCache();
					return this;
				},
				awakenSkill:function(skill,nounmark){
					if(!nounmark) this.unmarkSkill(skill);
					this.disableSkill(skill+'_awake',skill);
					this.awakenedSkills.add(skill);
					if(this.storage[skill]===false) this.storage[skill]=true;
					_status.event.clearStepCache();
					return this;
				},
				restoreSkill:function(skill,nomark){
					if(this.storage[skill]===true) this.storage[skill]=false;
					this.awakenedSkills.remove(skill);
					this.enableSkill(skill+'_awake',skill);
					if(!nomark) this.markSkill(skill);
					_status.event.clearStepCache();
					return this;
				},
				disableSkill:function(skill,skills){
					if(typeof skills=='string'){
						if(!this.disabledSkills[skills]){
							this.disabledSkills[skills]=[];
							var info=get.info(skills);
							if(info.ondisable&&info.onremove){
								if(typeof info.onremove=='function'){
									info.onremove(this,skill);
								}
								else if(typeof info.onremove=='string'){
									if(info.onremove=='storage'){
										delete this.storage[skill];
									}
									else{
										var cards=this.storage[skill];
										if(get.itemtype(cards)=='card'){
											cards=[cards];
										}
										if(get.itemtype(cards)=='cards'){
											if(this.onremove=='discard'){
												this.$throw(cards);
											}
											if(this.onremove=='discard'||this.onremove=='lose'){
												game.cardsDiscard(cards);
												delete this.storage[skill];
											}
										}
									}
								}
								else if(Array.isArray(info.onremove)){
									for(var i=0;i<info.onremove.length;i++){
										delete this.storage[info.onremove[i]];
									}
								}
								else if(info.onremove===true){
									delete this.storage[skill];
								}
							}
						}
						this.disabledSkills[skills].add(skill);
						var group=lib.skill[skills].group;
						if(typeof group=='string'||Array.isArray(group)){
							this.disableSkill(skill,group);
						}
					}
					else if(Array.isArray(skills)){
						for(var i=0;i<skills.length;i++){
							this.disableSkill(skill,skills[i]);
						}
					}
					_status.event.clearStepCache();
					return this;
				},
				enableSkill:function(skill){
					for(var i in this.disabledSkills){
						this.disabledSkills[i].remove(skill);
						if(this.disabledSkills[i].length==0){
							delete this.disabledSkills[i];
						}
					}
					_status.event.clearStepCache();
					return this;
				},
				checkMarks:function(){
					var skills=this.getSkills();
					game.expandSkills(skills);
					for(var i in this.marks){
						if(!skills.contains(i)&&!this.marks[i].info.fixed){
							this.unmarkSkill(i);
						}
					}
					return this;
				},
				addEquipTrigger:function(card){
					if(card){
						var info=get.info(card);
						if(info.skills){
							for(var j=0;j<info.skills.length;j++){
								this.addSkillTrigger(info.skills[j]);
							}
						}
					}
					else{
						var es=this.getCards('e');
						for(var i=0;i<es.length;i++){
							this.addEquipTrigger(es[i]);
						}
					}
					return this;
				},
				removeEquipTrigger:function(card){
					if(card){
						var info=get.info(card);
						var skills=this.getSkills(null,false);
						if(info.skills){
							for(var j=0;j<info.skills.length;j++){
								if(skills.contains(info.skills[j])) continue;
								this.removeSkillTrigger(info.skills[j]);
							}
						}
						if(info.clearLose&&typeof info.onLose=='function'){
							var next=game.createEvent('lose_'+card.name);
							next.setContent(info.onLose);
							next.player=this;
							next.card=card;
						}
					}
					else{
						var es=this.getCards('e');
						for(var i=0;i<es.length;i++){
							this.removeEquipTrigger(es[i]);
						}
					}
					return this;
				},
				removeSkillTrigger:function(skill,triggeronly){
					var info=lib.skill[skill];
					if(!info) return;
					if(typeof info.group=='string'){
						this.removeSkillTrigger(info.group);
					}
					else if(Array.isArray(info.group)){
						for(var i=0;i<info.group.length;i++){
							this.removeSkillTrigger(info.group[i]);
						}
					}
					if(!triggeronly) this.initedSkills.remove(skill);
					if(info.trigger){
						var playerid=this.playerid;
						var removeTrigger=function(i,evt){
							if(i=='global'){
								for(var j in lib.hook.globaltrigger){
									if(lib.hook.globaltrigger[j][playerid]){
										lib.hook.globaltrigger[j][playerid].remove(skill);
										if(lib.hook.globaltrigger[j][playerid].length==0){
											delete lib.hook.globaltrigger[j][playerid];
										}
										if(get.is.empty(lib.hook.globaltrigger[j])){
											delete lib.hook.globaltrigger[j];
										}
									}
								}
							}
							else{
								var name=playerid+'_'+i+'_'+evt;
								if(lib.hook[name]){
									lib.hook[name].remove(skill);
									if(lib.hook[name].length==0){
										delete lib.hook[name];
									}
								}
							}
						}
						for(var i in info.trigger){
							if(typeof info.trigger[i]=='string'){
								removeTrigger(i,info.trigger[i]);
							}
							else if(Array.isArray(info.trigger[i])){
								for(var j=0;j<info.trigger[i].length;j++){
									removeTrigger(i,info.trigger[i][j]);
								}
							}
						}
					}
					if(info.hookTrigger){
						if(this._hookTrigger){
							this._hookTrigger.remove(skill);
							if(!this._hookTrigger.length){
								delete this._hookTrigger;
							}
						}
					}
					return this;
				},
				removeSkill:function(skill){
					if(!skill) return;
					if(Array.isArray(skill)){
						for(var i=0;i<skill.length;i++){
							this.removeSkill(skill[i]);
						}
					}
					else{
						var info=lib.skill[skill];
						if(info&&info.fixed&&arguments[1]!==true) return skill;
						this.unmarkSkill(skill);
						game.broadcastAll(function(player,skill){
							player.skills.remove(skill);
							player.hiddenSkills.remove(skill);
							player.invisibleSkills.remove(skill);
							delete player.tempSkills[skill];
							for(var i in player.additionalSkills){
								player.additionalSkills[i].remove(skill);
							}
						},this,skill);
						this.checkConflict(skill);
						if(info){
							if(info.onremove){
								if(typeof info.onremove=='function'){
									info.onremove(this,skill);
								}
								else if(typeof info.onremove=='string'){
									if(info.onremove=='storage'){
										delete this.storage[skill];
									}
									else{
										var cards=this.storage[skill];
										if(get.itemtype(cards)=='card'){
											cards=[cards];
										}
										if(get.itemtype(cards)=='cards'){
											if(this.onremove=='discard'){
												this.$throw(cards);
											}
											if(this.onremove=='discard'||this.onremove=='lose'){
												game.cardsDiscard(cards);
												delete this.storage[skill];
											}
										}
									}
								}
								else if(Array.isArray(info.onremove)){
									for(var i=0;i<info.onremove.length;i++){
										delete this.storage[info.onremove[i]];
									}
								}
								else if(info.onremove===true){
									delete this.storage[skill];
								}
							}
							this.removeSkillTrigger(skill);
							if(!info.keepSkill){
								this.removeAdditionalSkill(skill);
							}
						}
						this.enableSkill(skill+'_awake');
					}
					return skill;
				},
				addTempSkill:function(skill,expire,checkConflict){
					if(this.hasSkill(skill)&&this.tempSkills[skill]==undefined) return;
					this.addSkill(skill,checkConflict,true,true);

					if(!expire){
						expire=['phaseAfter','phaseBefore'];
					}
					this.tempSkills[skill]=expire;

					if(typeof expire=='string'){
						lib.hookmap[expire]=true;
					}
					else if(Array.isArray(expire)){
						for(var i=0;i<expire.length;i++){
							lib.hookmap[expire[i]]=true;
						}
					}
					else if(get.objtype(expire)=='object'){
						var roles=['player','source','target'];
						for(var i=0;i<roles.length;i++){
							if(typeof expire[roles[i]]=='string'){
								lib.hookmap[expire[roles[i]]]=true;
							}
							else if(Array.isArray(expire[roles[i]])){
								for(var j=0;j<expire[roles[i]].length;j++){
									lib.hookmap[expire[roles[i]][j]]=true;
								}
							}
						}
						if(expire.global){
							if(typeof expire.global=='string'){
								lib.hookmap[expire.global]=true;
							}
							else if(Array.isArray(expire.global)){
								for(var i=0;i<expire.global.length;i++){
									lib.hookmap[expire.global[i]]=true;
								}
							}
						}
					}

					return skill;
				},
				attitudeTo:function(target){
					if(typeof get.attitude=='function') return get.attitude(this,target);
					return 0;
				},
				clearSkills:function(all){
					var list=[];
					var exclude=[];
					for(var i=0;i<arguments.length;i++){
						exclude.push(arguments[i]);
					}
					for(i=0;i<this.skills.length;i++){
						if(lib.skill[this.skills[i]].superCharlotte) continue;
						if(!all&&(lib.skill[this.skills[i]].temp||lib.skill[this.skills[i]].charlotte)) continue;
						if(!exclude.contains(this.skills[i])){
							list.push(this.skills[i]);
						}
					}
					if(all){
						for(var i in this.additionalSkills){
							this.removeAdditionalSkill(i);
						}
					}
					this.removeSkill(list);
					this.checkConflict();
					this.checkMarks();
					return list;
				},
				checkConflict:function(skill){
					if(skill){
						if(this.forbiddenSkills[skill]){
							delete this.forbiddenSkills[skill];
						}
						else{
							for(var i in this.forbiddenSkills){
								if(this.forbiddenSkills[i].remove(skill)){
									if(!this.forbiddenSkills[i].length){
										delete this.forbiddenSkills[i];
									}
								}
							}
						}
					}
					else{
						this.forbiddenSkills={};
						var forbid=[];
						var getName=function(arr){
							var str='';
							for(var i=0;i<arr.length;i++){
								str+=arr[i]+'+';
							}
							return str.slice(0,str.length-1);
						}
						var forbidlist=lib.config.forbid.concat(lib.config.customforbid);
						var skills=this.getSkills();
						for(var i=0;i<forbidlist.length;i++){
							if(lib.config.customforbid.contains(forbidlist[i])||
								!lib.config.forbidlist.contains(getName(forbidlist[i]))){
								for(var j=0;j<forbidlist[i].length;j++){
									if(!skills.contains(forbidlist[i][j])) break;
								}
								if(j==forbidlist[i].length){
									forbid.push(forbidlist[i]);
								}
							}
						}
						for(var i=0;i<forbid.length;i++){
							if(forbid[i][1]||this.name2){
								this.forbiddenSkills[forbid[i][0]]=this.forbiddenSkills[forbid[i][0]]||[];
								if(forbid[i][1]){
									this.forbiddenSkills[forbid[i][0]].add(forbid[i][1]);
								}
							}
						}
					}
				},
				getHistory:function(key,filter,last){
					if(!key) return this.actionHistory[this.actionHistory.length-1];
					if(!filter) return this.actionHistory[this.actionHistory.length-1][key];
					else{
						const history=this.getHistory(key);
						if(last){
							const lastIndex=history.indexOf(last);
							return history.filter((event,index)=>{
								if(index>lastIndex) return false;
								return filter(event);
							})
						}
						return history.filter(filter);
					}
				},
				checkHistory:function(key,filter,last){
					if(!key||!filter) return;
					else{
						const history=this.getHistory(key);
						if(last){
							const lastIndex=history.indexOf(last);
							history.forEach((event,index)=>{
								if(index>lastIndex) return false;
								filter(event);
							})
						}
						else{
							history.forEach(filter);
						}
					}
				},
				hasHistory:function(key,filter,last){
					const history=this.getHistory(key);
					if(!filter||typeof filter!="function") filter=lib.filter.all;
					if(last){
						const lastIndex=history.indexOf(last);
						return history.some((event,index)=>{
							if(index>lastIndex) return false;
							return filter(event);
						})
					}
					return history.some(filter);
				},
				getLastHistory:function(key,filter,last){
					let history=false;
					for(let i=this.actionHistory.length-1;i>=0;i--){
						if(this.actionHistory[i].isMe){
							history=this.actionHistory[i];break;
						}
					}
					if(!history) return null;
					if(!key) return history;
					if(!filter) return history[key];
					else{
						if(last){
							const lastIndex=history.indexOf(last);
							return history.filter((event,index)=>{
								if(index>lastIndex) return false;
								return filter(event);
							})
						}
						return history.filter(filter);
					}
				},
				checkAllHistory:function(key,filter,last){
					if(!key||!filter) return;
					this.actionHistory.forEach((value)=>{
						let history=value[key];
						if(last&&history.includes(last)){
							const lastIndex=history.indexOf(last);
							history.forEach((event,index)=>{
								if(index>lastIndex) return false;
								return filter(event);
							});
						}
						else{
							history.forEach(filter);
						}
					});
				},
				getAllHistory:function(key,filter,last){
					const history=[];
					this.actionHistory.forEach((value)=>{
						if(!key||!value[key]){
							history.push(value);
						}
						else{
							history.push(...value[key]);
						}
					})
					if(filter){
						if(last){
							const lastIndex=history.indexOf(last);
							return history.filter((event,index)=>{
								if(index>lastIndex) return false;
								return filter(event);
							});
						}
						return history.filter(filter);
					}
					return history;
				},
				hasAllHistory:function(key,filter,last){
					return this.actionHistory.some((value)=>{
						let history=value[key];
						if(last&&history.includes(last)){
							const lastIndex=history.indexOf(last);
							if(history.some(function(event,index){
								if(index>lastIndex) return false;
								return filter(event);
							})) return true;
						}
						else{
							if(history.some(filter)) return true;
						}
						return false;
					})
				},
				getLastUsed:function(num){
					if(typeof num!='number') num=0;
					var history=this.getHistory('useCard');
					if(history.length<=num) return null;
					return history[history.length-num-1];
				},
				getStat:function(key){
					if(!key) return this.stat[this.stat.length-1];
					return this.stat[this.stat.length-1][key];
				},
				getLastStat:function(key){
					var stat=false;
					for(var i=this.stat.length-1;i>=0;i--){
						if(this.stat[i].isMe){
							stat=this.stat[i];break;
						}
					}
					if(!stat) return null
					if(!key) return stat;
					return stat[key];
				},
				queue:function(time){
					if(time==false){
						clearTimeout(this.queueTimeout);
						this.queueCount=0;
						return;
					}
					if(time==undefined) time=500;
					var player=this;
					player.queueCount++;
					this.queueTimeout=setTimeout(function(){
						player.queueCount--;
						if(player.queueCount==0){
							player.style.transform='';
							player.node.avatar.style.transform='';
							player.node.avatar2.style.transform='';
							if(game.chess){
								ui.placeChess(player,player.dataset.position);
							}
							if(player==game.me) ui.me.removeAttribute('style');
						}
					},time)
				},
				getCardUsable:function(card,pure){
					var player=this;
					if(typeof card=='string'){
						card={name:card};
					}
					card=get.autoViewAs(card);
					var num=get.info(card).usable;
					if(typeof num=='function') num=num(card,player);
					num=game.checkMod(card,player,num,'cardUsable',player);
					if(typeof num!='number') return Infinity;
					if(!pure&&_status.currentPhase==player){
						return num-player.countUsed(card);
					}
					return num;
				},
				getAttackRange:function(raw){
					const player=this;
					let range=0;
					if(raw){
						range=game.checkMod(player,player,range,'globalFrom',player);
						range=game.checkMod(player,player,range,'attackFrom',player);
						const equips=player.getCards('e',function(card){
							return !ui.selected.cards||!ui.selected.cards.contains(card);
						});
						equips.forEach(card=>{
							const info=get.info(card,false).distance;
							if(ininfo&&info.globalFrom){
								range+=info.globalFrom;
							}
						})
						return (player.getEquipRange()-range);
					}
					let base=game.checkMod(player,'unchanged','attackRangeBase',player);
					if(base!='unchanged'){
						range=base;
					}
					else{
						range=player.getEquipRange();
					}
					range=game.checkMod(player,range,'attackRange',player);
					return range;
				},
				getEquipRange:function(cards){
					const player=this;
					if(!cards) cards=player.getCards('e',function(card){
						return !ui.selected.cards||!ui.selected.cards.contains(card);
					});
					const range=cards.reduce((range,card)=>{
						let newRange=false;
						const info=get.info(card,false);
						if(info.distance){
							//如果存在attackRange 则通过attackRange动态获取攻击范围
							if(typeof info.distance.attackRange=='function'){
								newRange=info.distance.attackRange(card,player);
							}
							//否则采用祖宗之法
							else if(typeof info.distance.attackFrom=='number'){
								newRange=(1-info.distance.attackFrom);
							}
						}
						let isN1=(typeof range=='number');
						let isN2=(typeof newRange=='number');
						if(isN1&&isN2) return Math.max(range,newRange);
						else return (isN1?range:newRange);
					},false);
					return (typeof range=='number')?range:1;
				},
				getGlobalFrom:function(){
					var player=this;
					var range=0;
					range=game.checkMod(player,player,range,'globalFrom',player);
					var equips=player.getCards('e',function(card){
						return !ui.selected.cards||!ui.selected.cards.contains(card);
					});
					for(var i=0;i<equips.length;i++){
						var info=get.info(equips[i]).distance;
						if(!info) continue;
						if(info.globalFrom){
							range+=info.globalFrom;
						}
					}
					return (-range);
				},
				getGlobalTo:function(){
					var player=this;
					var range=0;
					range=game.checkMod(player,player,range,'globalTo',player);
					var equips=player.getCards('e',function(card){
						return !ui.selected.cards||!ui.selected.cards.contains(card);
					});
					for(var i=0;i<equips.length;i++){
						var info=get.info(equips[i]).distance;
						if(!info) continue;
						if(info.globalTo){
							range+=info.globalTo;
						}
					}
					return (range);
				},
				getHandcardLimit:function(){
					var num=Math.max(this.hp,0);
					num=game.checkMod(this,num,'maxHandcardBase',this);
					num=game.checkMod(this,num,'maxHandcard',this);
					num=game.checkMod(this,num,'maxHandcardFinal',this);
					return Math.max(0,num);
				},
				getEnemies:function(func){
					var player=this;
					var targets;
					var mode=get.mode();
					if(mode=='identity'){
						if(_status.mode=='purple'){
							switch(player.identity){
								case 'bZhu':case 'bZhong':case 'rNei':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return ['rZhu','rZhong','bNei'].contains(target.identity);
								});break;
								case 'rZhu':case 'rZhong':case 'bNei':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return ['bZhu','bZhong','rNei'].contains(target.identity);
								});break;
								case 'rYe':case 'bYe':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return !['rYe','bYe'].contains(target.identity);
								});break;
							}
						}
						else{
							var num=get.population('fan');
							switch(player.identity){
								case 'zhu':case 'zhong':case 'mingzhong':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									if(num>=3) return target.identity=='fan';
									return target.identity=='nei'||target.identity=='fan';
								});break;
								case 'nei':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									if(num>=3) return target.identity=='fan';
									if(game.players.length==2) return target!=player;
									return target.identity=='zhong'||target.identity=='mingzhong'||target.identity=='fan';
								});break;
								case 'fan':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return target.identity!='fan';
								});break;
							}
						}
					}
					else if(mode=='guozhan'){
						if(player.identity=='ye'){
							targets=game.filterPlayer(function(target){
								if(func&&!func(target)) return false;
								return true;
							});
						}
						else{
							var group=lib.character[player.name1][1];
							targets=game.filterPlayer(function(target){
								if(func&&!func(target)) return false;
								return target.identity=='ye'||lib.character[target.name1][1]!=group;
							});
						}
					}
					else if(mode=='doudizhu'){
						targets=game.filterPlayer(function(target){
							if(func&&!func(target)) return false;
							return target.identity!=player.identity;
						});
					}
					else{
						targets=game.filterPlayer(function(target){
							if(func&&!func(target)) return false;
							return target.side!=player.side;
						});
					}
					targets.remove(player);
					return targets;
				},
				getFriends:function(func){
					var player=this;
					var targets;
					var mode=get.mode();
					var self=false;
					if(func===true){
						func=null;
						self=true;
					}
					if(mode=='identity'){
						if(_status.mode=='purple'){
							switch(player.identity){
								case 'rZhu':case 'rZhong':case 'bNei':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return ['rZhu','rZhong','bNei'].contains(target.identity);
								});break;
								case 'bZhu':case 'bZhong':case 'rNei':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return ['bZhu','bZhong','rNei'].contains(target.identity);
								});break;
								case 'rYe':case 'bYe':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return ['rYe','bYe'].contains(target.identity);
								});break;
							}
						}
						else{
							switch(player.identity){
								case 'zhu':case 'zhong':case 'mingzhong':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return ['zhu','zhong','mingzhong'].contains(target.identity);
								});break;
								case 'nei':targets=[];break;
								case 'fan':targets=game.filterPlayer(function(target){
									if(func&&!func(target)) return false;
									return target.identity=='fan';
								});break;
							}
						}
					}
					else if(mode=='guozhan'){
						if(player.identity=='ye'){
							targets=[];
						}
						else{
							var group=lib.character[player.name1][1];
							targets=game.filterPlayer(function(target){
								if(func&&!func(target)) return false;
								return target.identity!='ye'&&lib.character[target.name1][1]==group;
							});
						}
					}
					else if(mode=='doudizhu'){
						targets=game.filterPlayer(function(target){
							if(func&&!func(target)) return false;
							return target.identity==player.identity;
						});
					}
					else{
						targets=game.filterPlayer(function(target){
							if(func&&!func(target)) return false;
							return target.side==player.side;
						});
					}
					if(self){
						targets.add(player);
					}
					else{
						targets.remove(player);
					}
					return targets;
				},
				isEnemyOf:function(){
					return !this.isFriendOf.apply(this,arguments);
				},
				isFriendOf:function(player){
					if(get.mode()=='guozhan'){
						if(this==player) return true;
						if(this.getStorage('yexinjia_friend').includes(player)||player.getStorage('yexinjia_friend').includes(this)) return true;
						if(this.identity=='unknown'||this.identity=='ye') return false;
						if(player.identity=='unknown'||player.identity=='ye') return false;
						return this.identity==player.identity;
					}
					if(get.mode()=='doudizhu'){
						return this.identity==player.identity;
					}
					if(this.side!=undefined&&typeof player.side=='boolean'){
						return this.side==player.side;
					}
					return this==player;
				},
				isFriendsOf:function(player){
					return player.getFriends(true).contains(this);
				},
				isEnemiesOf:function(player){
					return player.getEnemies().contains(this);
				},
				isAlive:function(){
					return this.classList.contains('dead')==false;
				},
				isDead:function(){
					return this.classList.contains('dead');
				},
				isDying:function(){
					return _status.dying.contains(this)&&this.hp<=0&&this.isAlive();
				},
				isDamaged:function(){
					return this.hp<this.maxHp&&!this.storage.nohp;
				},
				isHealthy:function(){
					return this.hp>=this.maxHp||this.storage.nohp;
				},
				isMaxHp:function(only,raw){
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.getHp(raw)<this.getHp(raw):value.getHp(raw)<=this.getHp(raw);
					});
				},
				isMinHp:function(only,raw){
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.getHp(raw)>this.getHp(raw):value.getHp(raw)>=this.getHp(raw);
					});
				},
				isMaxCard:function(only){
					const numberOfCards=this.countCards('he');
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.countCards('he')<numberOfCards:value.countCards('he')<=numberOfCards;
					});
				},
				isMinCard:function(only){
					const numberOfCards=this.countCards('he');
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.countCards('he')>numberOfCards:value.countCards('he')>=numberOfCards;
					});
				},
				isMaxHandcard:function(only){
					const numberOfHandCards=this.countCards('h');
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.countCards('h')<numberOfHandCards:value.countCards('h')<=numberOfHandCards;
					});
				},
				isMinHandcard:function(only){
					const numberOfHandCards=this.countCards('h');
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.countCards('h')>numberOfHandCards:value.countCards('h')>=numberOfHandCards;
					});
				},
				isMaxEquip:function(only){
					const numberOfEquipAreaCards=this.countCards('e');
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.countCards('e')<numberOfEquipAreaCards:value.countCards('e')<=numberOfEquipAreaCards;
					});
				},
				isMinEquip:function(only){
					const numberOfEquipAreaCards=this.countCards('e');
					return game.players.every(value=>{
						if(value.isOut()||value==this) return true;
						return only?value.countCards('e')>numberOfEquipAreaCards:value.countCards('e')>=numberOfEquipAreaCards;
					});
				},
				isLinked:function(){
					if(get.is.linked2(this)){
						return this.classList.contains('linked2');
					}
					return this.classList.contains('linked');
				},
				isTurnedOver:function(){
					return this.classList.contains('turnedover');
				},
				isOut:function(){
					return this.classList.contains('out');
				},
				isMin:function(distance){
					if(distance&&lib.config.mode!='stone') return false;
					if(this.forcemin) return true;
					return this.classList.contains('minskin')&&!game.chess;
				},
				isIn:function(){
					return this.classList.contains('dead')==false&&this.classList.contains('out')==false&&!this.removed;
				},
				isUnseen:function(num){
					switch(num){
						case 0:return this.classList.contains('unseen');
						case 1:return this.classList.contains('unseen2');
						case 2:return this.classList.contains('unseen')||this.classList.contains('unseen2');
						default:return this.classList.contains('unseen')&&(!this.name2||this.classList.contains('unseen2'));
					}
				},
				isUnderControl:function(self,me){
					me=(me||game.me);
					var that=this._trueMe||this;
					if(that.isMad()||game.notMe) return false;
					if(this===me){
						if(self) return true;
						return false;
					}
					if(that===me||this==me._trueMe) return true;
					if(_status.connectMode) return false;
					if(lib.config.mode=='versus'){
						if(_status.mode=='three') return this.side==me.side;
						if(_status.mode=='standard') return lib.storage.single_control&&this.side==me.side;
						if(_status.mode=='four') return get.config('four_phaseswap')&&this.side==me.side;
						if(_status.mode=='two') return get.config('two_phaseswap')&&this.side==me.side;
						return false;
					}
					else if(lib.config.mode=='boss'){
						if(me.side) return false;
						return this.side==me.side&&get.config('single_control');
					}
					else if(game.chess){
						if(lib.config.mode=='chess'){
							if(_status.mode=='combat'&&!get.config('single_control')) return false;
						}
						return this.side==me.side;
					}
					return false;
				},
				isOnline:function(){
					if(this.ws&&lib.node&&!this.ws.closed&&this.ws.inited&&!this.isAuto){
						return true;
					}
					return false;
				},
				isOnline2:function(){
					if(this.ws&&lib.node&&!this.ws.closed){
						return true;
					}
					return false;
				},
				isOffline:function(){
					if(this.ws&&lib.node&&this.ws.closed){
						return true;
					}
					return false;
				},
				checkShow:function(skill,showonly){
					var sourceSkill=get.info(skill);
					var noshow=false;
					if(sourceSkill&&sourceSkill.sourceSkill){
						skill=sourceSkill.sourceSkill;
					}
					if(lib.skill.global.contains(skill)) return false;
					if(get.mode()!='guozhan'||game.expandSkills(this.getSkills()).contains(skill)){
						if(showonly){
							return false;
						}
						else{
							noshow=true;
						}
					}
					var unseen0=this.isUnseen(0);
					var name1=this.name1||this.name;
					if(lib.character[name1]&&(!showonly||unseen0)){
						var skills=game.expandSkills(lib.character[name1][3].slice(0));
						if(skills.contains(skill)){
							if(!noshow&&this.isUnseen(0)) this.showCharacter(0);
							return 'main';
						}
					}
					var unseen1=this.isUnseen(1);
					var name2=this.name2;
					if(lib.character[name2]&&(!showonly||unseen1)){
						var skills=game.expandSkills(lib.character[name2][3].slice(0));
						if(skills.contains(skill)){
							if(!noshow&&this.isUnseen(1)) this.showCharacter(1);
							return 'vice';
						}
					}
					return false;
				},
				needsToDiscard:function(num){
					if(typeof num!='number') num=0;
					return Math.max(0,num+this.countCards('h',card=>!this.canIgnoreHandcard(card))-this.getHandcardLimit());
				},
				distanceTo:function(target,method){
					return get.distance(this,target,method);
				},
				distanceFrom:function(target,method){
					return get.distance(target,this,method);
				},
				hasSkill:function(skill,arg2,arg3,arg4){
					return game.expandSkills(this.getSkills(arg2,arg3,arg4)).contains(skill);
				},
				hasStockSkill:function(skill,arg1,arg2,arg3){
					return game.expandSkills(this.getStockSkills(arg1,arg2,arg3)).contains(skill);
				},
				isZhu2:function(){
					var player=this,mode=get.mode();
					if(!this.isZhu) return false;
					if(mode=='identity') return true;
					if(mode=='versus'&&(_status.mode=='four'||_status.mode=='guandu')) return true;
					return false;
				},
				hasZhuSkill:function(skill,player){
					if(!this.hasSkill(skill)) return false;
					if(player){
						var mode=get.mode();
						if(mode=='identity'&&_status.mode=='purple'){
							if(this.identity.slice(0,1)!=player.identity.slice(0,1)) return false;
						}
						if(mode=='versus'&&(_status.mode=='four'||_status.mode=='guandu')){
							if(this.side!=player.side) return false;
						}
					}
					return true;
				},
				hasGlobalTag:function(tag,arg){
					var skills=lib.skill.global.slice(0);
					game.expandSkills(skills);
					for(var i=0;i<skills.length;i++){
						var info=lib.skill[skills[i]];
						if(info&&info.ai){
							if(info.ai.skillTagFilter&&info.ai[tag]&&
								info.ai.skillTagFilter(this,tag,arg)===false) continue;
							if(typeof info.ai[tag]=='string'){
								if(info.ai[tag]==arg) return true;
							}
							else if(info.ai[tag]){
								return true;
							}
						}
					}
					return false;
				},
				hasSkillTag:function(tag,hidden,arg,globalskill){
					var skills=this.getSkills(hidden);
					if(globalskill){
						skills.addArray(lib.skill.global);
					}
					game.expandSkills(skills);
					for(var i=0;i<skills.length;i++){
						var info=lib.skill[skills[i]];
						if(info&&info.ai){
							if(info.ai.skillTagFilter&&info.ai[tag]&&
								info.ai.skillTagFilter(this,tag,arg)===false) continue;
							if(typeof info.ai[tag]=='string'){
								if(info.ai[tag]==arg) return true;
							}
							else if(info.ai[tag]){
								return true;
							}
						}
					}
					return false;
				},
				hasJudge:function(name){
					if(name&&typeof name=='object'){
						name=name.viewAs||name.name;
					}
					var judges=this.getCards('j');
					for(var i=0;i<judges.length;i++){
						if((judges[i].viewAs||judges[i].name)==name){
							return true;
						}
					}
					return false;
				},
				hasFriend:function(){
					for(var i=0;i<game.players.length;i++){
						if(game.players[i].isOut()) continue;
						if(game.players[i]!=this&&get.attitude(game.players[i],this)>0){
							return true;
						}
					}
					return false;
				},
				hasUnknown:function(num){
					var mode=get.mode();
					if(typeof num!='number'){
						num=0;
					}
					if(mode=='identity'||mode=='guozhan'){
						for(var i=0;i<game.players.length;i++){
							if(game.players[i].ai.shown==0&&game.players[i]!=this){
								num--;
								if(num<=0){
									return true;
								}
							}
						}
					}
					return false;
				},
				isUnknown:function(player){
					var mode=get.mode();
					if(mode=='identity'||mode=='guozhan'){
						if(this.ai.shown==0&&this!=player){
							return true;
						}
					}
					return false;
				},
				hasWuxie:function(info){
					if(this.countCards('hs','wuxie')) return true;
					var skills=this.getSkills('invisible').concat(lib.skill.global);
					game.expandSkills(skills);
					for(var i=0;i<skills.length;i++){
						var ifo=get.info(skills[i]);
						if(ifo.hiddenWuxie&&info){
							if(typeof ifo.hiddenWuxie=='function'&&ifo.hiddenWuxie(this,info)){
								return true;
							}
						}
						else if(ifo.viewAs&&typeof ifo.viewAs!='function'&&ifo.viewAs.name=='wuxie'){
							if(!ifo.viewAsFilter||ifo.viewAsFilter(this)){
								return true;
							}
						}
						else{
							var hiddenCard=ifo.hiddenCard;
							if(typeof hiddenCard=='function'&&hiddenCard(this,'wuxie')){
								return true;
							}
						}
					}
					return false;
				},
				hasSha:function(respond,noauto){
					if(this.countCards('hs','sha')) return true;
					if(this.countCards('hs','hufu')) return true;
					if(!noauto&&this.countCards('hs','yuchanqian')) return true;
					if(this.hasSkillTag('respondSha',true,respond?'respond':'use',true)) return true;
					return this.hasUsableCard('sha');
				},
				hasShan:function(){
					if(this.countCards('hs','shan')) return true;
					if(this.countCards('hs','hufu')) return true;
					if(this.hasSkillTag('respondShan',true,null,true)) return true;
					return this.hasUsableCard('shan');
				},
				mayHaveSha:function(viewer,type){
					if((this.hp>2||!this.isZhu&&this.hp>1)&&this.hasSkillTag('respondSha',true,type,true)) return true;
					if(get.itemtype(viewer)!=='player') viewer=_status.event.player;
					let cards;
					if(this===viewer||get.itemtype(viewer)==='player'&&viewer.hasSkillTag('viewHandcard',null,this,true)) cards=this.getCards('h');
					else cards=this.getShownCards();
					if(cards.some(card=>{
						let name=get.name(card,this);
						if(name=='sha'||name=='hufu'||name=='yuchanqian'){
							if(type==='use') return lib.filter.cardEnabled(card,this);
							if(type==='respond') return lib.filter.cardRespondable(card,this);
							return true;
						}
						return false;
					})) return true;
					let hs=this.getCards('hs').removeArray(cards).length;
					if(hs===0) return false;
					return Math.pow(hs+(this.isPhaseUsing()?6:4),2)>100*_status.event.getRand('mayHaveSha');
				},
				mayHaveShan:function(viewer,type){
					if((this.hp>2||!this.isZhu&&this.hp>1)&&this.hasSkillTag('respondShan',true,type,true)) return true;
					if(get.itemtype(viewer)!=='player') viewer=_status.event.player;
					let cards;
					if(this===viewer||get.itemtype(viewer)==='player'&&viewer.hasSkillTag('viewHandcard',null,this,true)) cards=this.getCards('h');
					else cards=this.getShownCards();
					if(cards.some(card=>{
						let name=get.name(card,this);
						if(name==='shan'||name==='hufu'){
							if(type==='use') return lib.filter.cardEnabled(card,this);
							if(type==='respond') return lib.filter.cardRespondable(card,this);
							return true;
						}
						return false;
					})) return true;
					let hs=this.getCards('hs').removeArray(cards).length;
					if(hs===0) return false;
					return Math.pow(hs+(this.isPhaseUsing()?3:5),2)>100*_status.event.getRand('mayHaveShan');
				},
				hasCard:function(name,position){
					if(typeof name=='function'){
						var hs=this.getCards(position);
						for(var i=0;i<hs.length;i++){
							if(name(hs[i])) return true;
						}
					}
					else{
						if(this.countCards(position,name)) return true;
					}
					return false;
				},
				getEquip:function(name){
					var es=this.getCards('e');
					if(typeof name=='object'&&get.info(name)){
						name=get.info(name).subtype;
						if(name){
							name=parseInt(name[5]);
						}
					}
					else if(typeof name=='string'&&name.startsWith('equip')&&name.length==6){
						name=parseInt(name[5]);
					}
					if(!name){
						return null;
					}
					for(var i=0;i<es.length;i++){
						if(typeof name==='number'){
							if(get.info(es[i]).subtype==='equip'+name){
								return es[i];
							}
						}
						else{
							if(es[i].name===name) return es[i];
							var source=get.info(es[i]).source;
							if(Array.isArray(source)&&source.contains(name)){
								return es[i];
							}
						}
					}
					return null;
				},
				getJudge:function(name){
					var judges=this.node.judges.childNodes;
					for(var i=0;i<judges.length;i++){
						if(judges[i].classList.contains('removing')) continue;
						if((judges[i].viewAs||judges[i].name)==name){
							return judges[i];
						}
					}
					return null;
				},
				$drawAuto:function(cards,target){
					if(this.isUnderControl(true,target)){
						this.$draw(cards);
					}
					else{
						this.$draw(cards.length);
					}
				},
				$draw:function(num,init,config){
					if(init!==false&&init!=='nobroadcast'){
						game.broadcast(function(player,num,init,config){
							player.$draw(num,init,config)
						},this,num,init,config);
					}
					var cards,node;
					if(get.itemtype(num)=='cards'){
						cards=num;
						num=cards.length;
					}
					else if(get.itemtype(num)=='card'){
						cards=[num];
						num=1;
					}
					if(init!==false){
						if(cards){
							game.addVideo('drawCard',this,get.cardsInfo(cards));
						}
						else{
							game.addVideo('draw',this,num);
						}
					}
					if(cards){
						cards=cards.slice(0);
						node=cards.shift().copy('thrown','drawingcard');
					}
					else{
						node=ui.create.div('.card.thrown.drawingcard');
					}
					node.fixed=true;
					node.hide();

					var dx,dy;
					if(game.chess){
						var rect=this.getBoundingClientRect();

						if(rect.left<=80){
							dx=-10;
							if(rect.top<=80){
								dy=-10;
							}
							else if(rect.top+rect.height+80>=ui.chessContainer.offsetHeight){
								dy=10;
							}
							else{
								dy=0;
							}
						}
						else if(rect.left+rect.width+80>=ui.chessContainer.offsetWidth){
							dx=10;
							if(rect.top<=80){
								dy=-10;
							}
							else if(rect.top+rect.height+80>=ui.chessContainer.offsetHeight){
								dy=10;
							}
							else{
								dy=0;
							}
						}
						else if(rect.top<=80){
							dx=0;
							dy=-10;
						}
						else if(rect.top+rect.height+80>=ui.chessContainer.offsetHeight){
							dx=0;
							dy=10;
						}
						else{
							dx=rect.left+this.offsetWidth/2-ui.arena.offsetWidth/2;
							dy=rect.top+this.offsetHeight/2-ui.arena.offsetHeight/2;
						}

						var coeff=240/Math.sqrt(dx*dx+dy*dy);
						dx*=coeff;
						dy*=coeff;

						node.style.left=(this.getLeft()+this.offsetWidth/2-52-dx)+'px';
						node.style.top=(this.getTop()+this.offsetHeight/2-52-dy)+'px';
						this.parentNode.appendChild(node);
					}
					else{
						this.parentNode.appendChild(node);
						node.style.left='calc(50% - 52px)';
						node.style.top='calc(50% - 52px)';

						dx=this.getLeft()+this.offsetWidth/2-52-node.offsetLeft;
						dy=this.getTop()+this.offsetHeight/2-52-node.offsetTop;

						if(get.is.mobileMe(this)){
							dx+=get.cardOffset();
							if(ui.arena.classList.contains('oblongcard')){
								dy-=16;
							}
						}
					}
					node.style.transitionDuration='0.8s';
					ui.refresh(node);
					if(typeof num=='number'&&init!==false){
						config={
							total:num,
							current:1
						}
					}
					if(config&&config.total>1){
						var total=config.total,current=config.current;
						var dxtotal;
						if(total<=5){
							dxtotal=Math.min(80,(total-1)*20);
							dx+=-dxtotal+2*dxtotal*(current-1)/(total-1)
						}
						else{
							var total2=Math.floor(total/2);
							if(current<=total2){
								total=total2;
								dy-=20;
							}
							else{
								current-=total2;
								total-=total2;
								dy+=20;
							}
							dxtotal=Math.min(80,(total-1)*20);
							dx+=-dxtotal+2*dxtotal*(current-1)/(total-1)
						}
						config.current++;
					}
					if(node.style.transform&&node.style.transform!='none'&&node.style.transform.indexOf('translate')==-1){
						node.style.transform+=' translate('+dx+'px,'+dy+'px)';
					}
					else{
						node.style.transform='translate('+dx+'px,'+dy+'px)';
					}
					node.show();

					node.listenTransition(function(){
						node.style.transitionDuration='0.5s';
						ui.refresh(node);
						node.delete();
					});
					var that=this;
					if(num&&num>1){
						if(config&&config.total>1){
							setTimeout(function(){
								if(cards){
									that.$draw(cards,false,config)
								}
								else{
									that.$draw(num-1,false,config)
								}
							},50)
						}
						else{
							setTimeout(function(){
								if(cards){
									that.$draw(cards,false,config)
								}
								else{
									that.$draw(num-1,false,config)
								}
							},200);
						}
					}
				},
				$compareMultiple:function(card1,targets,cards){
					game.broadcast(function(player,card1,targets,cards){
						player.$compareMultiple(card1,targets,cards);
					},this,card1,targets,cards);
					game.addVideo('compareMultiple',this,[get.cardInfo(card1),get.targetsInfo(targets),get.cardsInfo(cards)]);
					var player=this;
					var node1=player.$throwxy2(card1,
						'calc(50% - 52px)','calc(50% + 10px)','perspective(600px) rotateY(180deg)',true
					);
					if(lib.config.cardback_style!='default'){
						node1.style.transitionProperty='none';
						ui.refresh(node1);
						node1.classList.add('infohidden');
						ui.refresh(node1);
						node1.style.transitionProperty='';
					}
					else{
						node1.classList.add('infohidden');
					}

					node1.style.transform='perspective(600px) rotateY(180deg) translateX(0)';
					var onEnd01=function(){
						//node1.removeEventListener('webkitTransitionEnd',onEnd01);
						setTimeout(function(){
							node1.style.transition='all ease-in 0.3s';
							node1.style.transform='perspective(600px) rotateY(270deg) translateX(52px)';
							var onEnd=function(){
								node1.classList.remove('infohidden');
								node1.style.transition='all 0s';
								ui.refresh(node1);
								node1.style.transform='perspective(600px) rotateY(-90deg) translateX(52px)';
								ui.refresh(node1);
								node1.style.transition='';
								ui.refresh(node1);
								node1.style.transform='';
								//node1.removeEventListener('webkitTransitionEnd',onEnd);
							}
							node1.listenTransition(onEnd);
						},300);
					};
					node1.listenTransition(onEnd01);

					setTimeout(function(){
						var left0=-targets.length*52-(targets.length-1)*8;
						for(var i=0;i<targets.length;i++){
							(function(target,card2,i){
								var left=left0+i*120;
								var node2;
								if(left<0){
									node2=target.$throwxy2(card2,
										'calc(50% - '+(-left)+'px)','calc(50% - 114px)','perspective(600px) rotateY(180deg)',true
									);
								}
								else{
									node2=target.$throwxy2(card2,
										'calc(50% + '+left+'px)','calc(50% - 114px)','perspective(600px) rotateY(180deg)',true
									);
								}
								if(lib.config.cardback_style!='default'){
									node2.style.transitionProperty='none';
									ui.refresh(node2);
									node2.classList.add('infohidden');
									ui.refresh(node2);
									node2.style.transitionProperty='';
								}
								else{
									node2.classList.add('infohidden');
								}
								node2.style.transform='perspective(600px) rotateY(180deg) translateX(0)';
								var onEnd02=function(){
									//node2.removeEventListener('webkitTransitionEnd',onEnd02);
									setTimeout(function(){
										node2.style.transition='all ease-in 0.3s';
										node2.style.transform='perspective(600px) rotateY(270deg) translateX(52px)';
										var onEnd=function(){
											node2.classList.remove('infohidden');
											node2.style.transition='all 0s';
											ui.refresh(node2);
											node2.style.transform='perspective(600px) rotateY(-90deg) translateX(52px)';
											ui.refresh(node2);
											node2.style.transition='';
											ui.refresh(node2);
											node2.style.transform='';
											//node2.removeEventListener('webkitTransitionEnd',onEnd);
										}
										node2.listenTransition(onEnd);
									},200);
								};
								node2.listenTransition(onEnd02);
							}(targets[i],cards[i],i))
						}
					},200);
				},
				$compare:function(card1,target,card2){
					game.broadcast(function(player,target,card1,card2){
						player.$compare(card1,target,card2);
					},this,target,card1,card2);
					game.addVideo('compare',this,[get.cardInfo(card1),target.dataset.position,get.cardInfo(card2)]);
					var player=this;
					var node1=player.$throwxy2(card1,
						'calc(50% - 114px)','calc(50% - 52px)','perspective(600px) rotateY(180deg)',true
					);
					if(lib.config.cardback_style!='default'){
						node1.style.transitionProperty='none';
						ui.refresh(node1);
						node1.classList.add('infohidden');
						ui.refresh(node1);
						node1.style.transitionProperty='';
					}
					else{
						node1.classList.add('infohidden');
					}

					node1.style.transform='perspective(600px) rotateY(180deg) translateX(0)';
					var onEnd01=function(){
						//node1.removeEventListener('webkitTransitionEnd',onEnd01);
						setTimeout(function(){
							node1.style.transition='all ease-in 0.3s';
							node1.style.transform='perspective(600px) rotateY(270deg) translateX(52px)';
							var onEnd=function(){
								node1.classList.remove('infohidden');
								node1.style.transition='all 0s';
								ui.refresh(node1);
								node1.style.transform='perspective(600px) rotateY(-90deg) translateX(52px)';
								ui.refresh(node1);
								node1.style.transition='';
								ui.refresh(node1);
								node1.style.transform='';
								//node1.removeEventListener('webkitTransitionEnd',onEnd);
							}
							node1.listenTransition(onEnd);
						},300);
					};
					node1.listenTransition(onEnd01);
					setTimeout(function(){
						var node2=target.$throwxy2(card2,
							'calc(50% + 10px)','calc(50% - 52px)','perspective(600px) rotateY(180deg)',true
						);
						if(lib.config.cardback_style!='default'){
							node2.style.transitionProperty='none';
							ui.refresh(node2);
							node2.classList.add('infohidden');
							ui.refresh(node2);
							node2.style.transitionProperty='';
						}
						else{
							node2.classList.add('infohidden');
						}
						node2.style.transform='perspective(600px) rotateY(180deg) translateX(0)';
						var onEnd02=function(){
							//node2.removeEventListener('webkitTransitionEnd',onEnd02);
							setTimeout(function(){
								node2.style.transition='all ease-in 0.3s';
								node2.style.transform='perspective(600px) rotateY(270deg) translateX(52px)';
								var onEnd=function(){
									node2.classList.remove('infohidden');
									node2.style.transition='all 0s';
									ui.refresh(node2);
									node2.style.transform='perspective(600px) rotateY(-90deg) translateX(52px)';
									ui.refresh(node2);
									node2.style.transition='';
									ui.refresh(node2);
									node2.style.transform='';
									//node2.removeEventListener('webkitTransitionEnd',onEnd);
								}
								node2.listenTransition(onEnd);
							},200);
						};
						node2.listenTransition(onEnd02);
					},200);
				},
				$throw:function(card,time,init,nosource){
					if(typeof card=='number'){
						var tmp=card;
						card=[];
						while(tmp--){
							var cardx=ui.create.card();
							cardx.classList.add('infohidden');
							cardx.classList.add('infoflip');
							card.push(cardx);
						}
					}
					if(init!==false){
						if(init!=='nobroadcast'){
							game.broadcast(function(player,card,time,init,nosource){
								player.$throw(card,time,init,nosource);
							},this,card,time,init);
						}
						if(get.itemtype(card)!='cards'){
							if(get.itemtype(card)=='card'){
								card=[card];
							}
							else{
								return;
							}
						}
						game.addVideo('throw',this,[get.cardsInfo(card),time,nosource]);
					}
					if(game.chess){
						this.chessFocus();
					}
					if(get.itemtype(card)=='cards'){
						var node;
						for(var i=0;i<card.length;i++){
							node=this.$throw(card[i],time,false,nosource);
						}
						return node;
					}
					else{
						var node;
						if(card==undefined||card.length==0) return;
						node=this.$throwordered(card.copy('thrown'),nosource);
						if(time!=undefined){
							node.fixed=true;
							setTimeout(function(){node.delete()},time);
						}
						lib.listenEnd(node);
						return node;
					}
				},
				$throwordered:function(){
					return this.$throwordered2.apply(this,arguments);
					// if(lib.config.low_performance){
					// 	return this.$throwordered2.apply(this,arguments);
					// }
					// else{
					// 	return this.$throwordered1.apply(this,arguments);
					// }
				},
				$throwordered1:function(node,nosource){
					node.classList.add('thrown');
					node.hide();
					node.style.transitionProperty='left,top,opacity,transform';
					for(var i=0;i<ui.thrown.length;i++){
						if(ui.thrown[i].parentNode!=ui.arena||
							ui.thrown[i].classList.contains('removing')){
							ui.thrown.splice(i--,1);
						}
					}
					ui.thrown.push(node);
					var uithrowns=ui.thrown.slice(0);
					var tops;
					if(game.chess){
						switch(Math.floor((ui.thrown.length-1)/4)){
							case 0:
								tops=['calc(50% - 82px)'];
								break;
							case 1:
								tops=['calc(50% - 139px)','calc(50% - 25px)'];
								break;
							case 2:
								tops=['calc(50% - 196px)','calc(50% - 82px)','calc(50% + 32px)'];
								break;
							default:
								tops=['calc(50% - 253px)','calc(50% - 139px)',
									'calc(50% - 25px)','calc(50% + 89px)'];
						}
					}
					else{
						switch(Math.floor((ui.thrown.length-1)/4)){
							case 0:
								tops=['calc(50% - 52px)'];
								break;
							case 1:
								tops=['calc(50% - 109px)','calc(50% + 5px)'];
								break;
							case 2:
								tops=['calc(50% - 166px)','calc(50% - 52px)','calc(50% + 62px)'];
								break;
							default:
								tops=['calc(50% - 223px)','calc(50% - 109px)',
									'calc(50% + 5px)','calc(50% + 119px)'];
						}
					}
					while(uithrowns.length){
						var throwns=uithrowns.splice(0,Math.min(uithrowns.length,4));
						switch(throwns.length){
							case 1:
								throwns[0].style.left='calc(50% - 52px)';
								break;
							case 2:
								throwns[0].style.left='calc(50% - 109px)';
								throwns[1].style.left='calc(50% + 5px)';
								break;
							case 3:
								throwns[0].style.left='calc(50% - 166px)';
								throwns[1].style.left='calc(50% - 52px)';
								throwns[2].style.left='calc(50% + 62px)';
								break;
							case 4:
								throwns[0].style.left='calc(50% - 223px)';
								throwns[1].style.left='calc(50% - 109px)';
								throwns[2].style.left='calc(50% + 5px)';
								throwns[3].style.left='calc(50% + 119px)';
								break;
						}
						var top;
						if(tops.length){
							top=tops.shift();
						}
						else{
							if(game.chess){
								top='calc(50% - 82px)';
							}
							else{
								top='calc(50% - 52px)';
							}
						}
						for(var i=0;i<throwns.length;i++){
							throwns[i].style.top=top;
						}
					}
					if(nosource){
						node.style.transform='scale(0)';
						node.classList.add('center');
					}
					else{
						var parseCalc=function(str){
							var per=str.slice(str.indexOf('calc(')+5,str.indexOf('%'));
							var add=str.slice(str.indexOf('%')+1,str.indexOf('px')).replace(/\s/g,'');
							return [parseInt(per),parseInt(add)];
						}
						var nx=parseCalc(node.style.left);
						var ny=parseCalc(node.style.top);
						nx=nx[0]*ui.arena.offsetWidth/100+nx[1];
						ny=ny[0]*ui.arena.offsetHeight/100+ny[1];
						var dx,dy;
						if(game.chess){
							var rect=this.getBoundingClientRect();
							dx=rect.left+this.offsetWidth/2-52-nx;
							dy=rect.top+this.offsetHeight/2-52-ny;
						}
						else{
							dx=this.getLeft()+this.offsetWidth/2-52-nx;
							dy=this.getTop()+this.offsetHeight/2-52-ny;
							if(get.is.mobileMe(this)){
								dx+=get.cardOffset();
								if(ui.arena.classList.contains('oblongcard')){
									dy-=16;
								}
							}
						}
						if(node.style.transform&&node.style.transform!='none'&&node.style.transform.indexOf('translate')==-1){
							node.style.transform+=' translate('+dx+'px,'+dy+'px)';
						}
						else{
							node.style.transform='translate('+dx+'px,'+dy+'px)';
						}
					}
					ui.arena.appendChild(node);
					ui.refresh(node);
					node.style.transform='';
					node.show();
					lib.listenEnd(node);
					return node;
				},
				$throwordered2:function(node,nosource){
					node.classList.add('thrown');
					node.classList.add('center');
					node.hide();
					node.style.transitionProperty='left,top,opacity,transform';

					if(nosource){
						// node.style.transform='scale(0)';
					}
					else{
						var nx=[50,-52];
						var ny=[50,-52];
						nx=nx[0]*ui.arena.offsetWidth/100+nx[1];
						ny=ny[0]*ui.arena.offsetHeight/100+ny[1];
						var dx,dy;
						if(game.chess){
							var rect=this.getBoundingClientRect();
							dx=rect.left+this.offsetWidth/2-52-nx;
							dy=rect.top+this.offsetHeight/2-52-ny;
						}
						else{
							dx=this.getLeft()+this.offsetWidth/2-52-nx;
							dy=this.getTop()+this.offsetHeight/2-52-ny;
							if(get.is.mobileMe(this)){
								dx+=get.cardOffset();
								if(ui.arena.classList.contains('oblongcard')){
									dy-=16;
								}
							}
						}
						if(node.style.transform&&node.style.transform!='none'&&node.style.transform.indexOf('translate')==-1){
							node.style.transform+=' translate('+dx+'px,'+dy+'px)';
						}
						else{
							node.style.transform='translate('+dx+'px,'+dy+'px)';
						}
					}
					ui.arena.appendChild(node);
					ui.refresh(node);

					for(var i=0;i<ui.thrown.length;i++){
						if(ui.thrown[i].parentNode!=ui.arena||
							ui.thrown[i].classList.contains('removing')){
							ui.thrown.splice(i--,1);
						}
					}
					ui.thrown.push(node);
					var uithrowns=ui.thrown.slice(0);
					var tops;
					switch(Math.floor((ui.thrown.length-1)/4)){
						case 0:
							tops=[0];
							break;
						case 1:
							tops=[-57,57];
							break;
						case 2:
							tops=[-114,0,114];
							break;
						default:
							tops=[-171,-57,57,171];
					}
					while(uithrowns.length){
						var throwns=uithrowns.splice(0,Math.min(uithrowns.length,4));
						switch(throwns.length){
							case 1:
								throwns[0]._transthrown='translate(0px,';
								break;
							case 2:
								throwns[0]._transthrown='translate(-57px,';
								throwns[1]._transthrown='translate(57px,';
								break;
							case 3:
								throwns[0]._transthrown='translate(-114px,';
								throwns[1]._transthrown='translate(0,';
								throwns[2]._transthrown='translate(114px,';
								break;
							case 4:
								throwns[0]._transthrown='translate(-171px,';
								throwns[1]._transthrown='translate(-57px,';
								throwns[2]._transthrown='translate(57px,';
								throwns[3]._transthrown='translate(171px,';
								break;
						}
						var top;
						if(tops.length){
							top=tops.shift();
						}
						else{
							top=0;
						}
						if(game.chess){
							top-=30;
						}
						for(var i=0;i<throwns.length;i++){
							throwns[i].style.transform=throwns[i]._transthrown+top+'px)';
							delete throwns[i]._transthrown;
						}
					}

					node.show();
					lib.listenEnd(node);
					return node;
				},
				$throwxy:function(card,left,top){
					var node=card.copy('thrown','thrownhighlight');
					node.dataset.position=this.dataset.position;
					node.hide();
					node.style.transitionProperty='left,top,opacity';

					ui.arena.appendChild(node);
					ui.refresh(node);
					node.show();
					node.style.left=left;
					node.style.top=top;
					lib.listenEnd(node);
					return node;
				},
				$throwxy2:function(card,left,top,trans,flipx,flipy){
					if(game.chess){
						return this.$throwxy.apply(this,arguments);
					}
					var node=card.copy('thrown','thrownhighlight');
					node.style.left=left;
					node.style.top=top;
					node.hide();
					// node.style.transitionProperty='left,top,opacity,transform';

					var parseCalc=function(str){
						var per=str.slice(str.indexOf('calc(')+5,str.indexOf('%'));
						var add=str.slice(str.indexOf('%')+1,str.indexOf('px')).replace(/\s/g,'');
						return [parseInt(per),parseInt(add)];
					}
					var nx=parseCalc(node.style.left);
					var ny=parseCalc(node.style.top);
					nx=nx[0]*ui.arena.offsetWidth/100+nx[1];
					ny=ny[0]*ui.arena.offsetHeight/100+ny[1];
					var dx=this.getLeft()+this.offsetWidth/2-52-nx;
					var dy=this.getTop()+this.offsetHeight/2-52-ny;
					if(flipx) dx=-dx;
					if(flipy) dy=-dy;
					if(trans){
						node.style.transform=trans+' translate('+dx+'px,'+dy+'px)';
					}
					else{
						node.style.transform='translate('+dx+'px,'+dy+'px)';
					}

					ui.arena.appendChild(node);
					ui.refresh(node);
					node.show();
					// node.style.transform=trans||'';
					lib.listenEnd(node);
					return node;
				},
				throwDice:function(num){
					if(typeof num!='number'){
						num=get.rand(6)+1;
						_status.event.num=num;
					}
					if(!game.online){
						game.pause();
					}
					game.broadcastAll(function(num){
						var diceContainer=ui.create.div('.fullsize.dice-container',ui.window);
						ui.window.classList.add('dicepaused');
						var dice=ui.create.div('.dice');
						var side;

						side=ui.create.div('.side.front',dice);
						ui.create.div('.dot.center',side);
						ui.create.div('.side.front.inner',dice);

						side=ui.create.div('.side.top',dice);
						ui.create.div('.dot.dtop.dleft',side);
						ui.create.div('.dot.dbottom.dright',side);
						ui.create.div('.side.top.inner',dice);

						side=ui.create.div('.side.right',dice);
						ui.create.div('.dot.dtop.dleft',side);
						ui.create.div('.dot.center',side);
						ui.create.div('.dot.dbottom.dright',side);
						ui.create.div('.side.right.inner',dice);

						side=ui.create.div('.side.left',dice);
						ui.create.div('.dot.dtop.dleft',side);
						ui.create.div('.dot.dtop.dright',side);
						ui.create.div('.dot.dbottom.dleft',side);
						ui.create.div('.dot.dbottom.dright',side);
						ui.create.div('.side.left.inner',dice);

						side=ui.create.div('.side.bottom',dice);
						ui.create.div('.dot.center',side);
						ui.create.div('.dot.dtop.dleft',side);
						ui.create.div('.dot.dtop.dright',side);
						ui.create.div('.dot.dbottom.dleft',side);
						ui.create.div('.dot.dbottom.dright',side);
						ui.create.div('.side.bottom.inner',dice);

						side=ui.create.div('.side.back',dice);
						ui.create.div('.dot.dtop.dleft',side);
						ui.create.div('.dot.dtop.dright',side);
						ui.create.div('.dot.dbottom.dleft',side);
						ui.create.div('.dot.dbottom.dright',side);
						ui.create.div('.dot.center dleft',side);
						ui.create.div('.dot.center dright',side);
						ui.create.div('.side.back.inner',dice);

						ui.create.div('.side.cover.x',dice);
						ui.create.div('.side.cover.y',dice);
						ui.create.div('.side.cover.z',dice);

						var map={
							1:[75,0,45],
							2:[-15,45,0],
							3:[165,-45,90],
							4:[345,-45,90],
							5:[345,-45,180],
							6:[255,0,135]
						};
						dice.roll=function(deg){
							if(typeof deg=='number'){
								dice.current[0]+=deg;
								deg=dice.current;
							}
							deg=deg.slice(0);
							dice.current=deg;
							this.style.transform='rotateX('+deg[0]+'deg) rotateY('+deg[1]+'deg) rotateZ('+deg[2]+'deg)';
						};
						dice.roll(map[num]);
						diceContainer.appendChild(dice);
						ui.refresh(dice);
						dice.roll(1025);

						dice.addEventListener('webkitTransitionEnd',function(){
							if(!dice.over){
								dice.style.transition='transform 0.8s ease';
								dice.roll(-20);
								dice.over=true;
							}
							else if(!dice.resumed){
								setTimeout(function(){
									diceContainer.delete();
									ui.window.classList.remove('dicepaused');
								},300);
								if(!game.online){
									setTimeout(game.resume,800);
								}
								dice.resumed=true;
							}
						});
					},num);
				},
				$giveAuto:function(card,player){
					if(Array.isArray(card)&&card.length==0) return;
					var args=Array.from(arguments);
					if(_status.connectMode||(!this.isUnderControl(true)&&!player.isUnderControl(true))){
						if(Array.isArray(card)){
							card=card.length;
						}
						else{
							card=1;
						}
						args[0]=card;
					}
					return this.$give.apply(this,args);
				},
				$give:function(card,player,log,init){
					if(init!==false){
						game.broadcast(function(source,card,player,init){
							source.$give(card,player,false,init);
						},this,card,player,init);
						if(typeof card=='number'&&card>=0){
							game.addVideo('give',this,[card,player.dataset.position]);
						}
						else{
							if(get.itemtype(card)=='card'){
								card=[card];
							}
							if(get.itemtype(card)=='cards'){
								game.addVideo('giveCard',this,[get.cardsInfo(card),player.dataset.position]);
							}
						}
					}
					if(get.itemtype(card)=='cards'){
						if(log!=false&&!_status.video){
							game.log(player,'从',this,'获得了',card);
						}
						if(this.$givemod){
							this.$givemod(card,player);
						}
						else{
							for(var i=0;i<card.length;i++){
								this.$give(card[i],player,false,false);
							}
						}
					}
					else if(typeof card=='number'&&card>=0){
						if(log!=false&&!_status.video){
							game.log(player,'从',this,'获得了'+get.cnNumber(card)+'张牌');
						}
						if(this.$givemod){
							this.$givemod(card,player);
						}
						else{
							while(card--) this.$give('',player,false,false);
						}
					}
					else{
						if(log!=false&&!_status.video){
							if(get.itemtype(card)=='card'&&log!=false){
								game.log(player,'从',this,'获得了',card);
							}
							else{
								game.log(player,'从',this,'获得了一张牌');
							}
						}
						if(this.$givemod){
							this.$givemod(card,player);
						}
						else{
							var node;
							if(get.itemtype(card)=='card'){
								node=card.copy('card','thrown',false);
							}
							else{
								node=ui.create.div('.card.thrown');
							}
							// node.dataset.position=this.dataset.position;
							node.fixed=true;
							this.$throwordered(node);
							// lib.listenEnd(node);
							// node.hide();
							// node.style.transitionProperty='left,top,opacity';
							//
							// node.style.transform='rotate('+(Math.random()*16-8)+'deg)';
							//
							// ui.arena.appendChild(node);
							// ui.refresh(node);
							// node.show();
							// node.style.left='calc(50% - 52px '+((Math.random()-0.5<0)?'+':'-')+' '+Math.random()*100+'px)';
							// node.style.top='calc(50% - 52px '+((Math.random()-0.5<0)?'+':'-')+' '+Math.random()*80+'px)';

							node.listenTransition(function(){
								var dx=player.getLeft()+player.offsetWidth/2-52-node.offsetLeft;
								var dy=player.getTop()+player.offsetHeight/2-52-node.offsetTop;
								if(node.style.transform&&node.style.transform!='none'&&node.style.transform.indexOf('translate')==-1){
									node.style.transform+=' translate('+dx+'px,'+dy+'px)';
								}
								else{
									node.style.transform='translate('+dx+'px,'+dy+'px)';
								}

								node.delete();
							});
							// setTimeout(function(){
							// 	// node.removeAttribute('style');
							// 	// node.dataset.position=player.dataset.position;
							// 	var dx=player.offsetLeft+player.offsetWidth/2-52-node.offsetLeft;
							// 	var dy=player.offsetTop+player.offsetHeight/2-52-node.offsetTop;
							// 	if(node.style.transform&&node.style.transform!='none'&&node.style.transform.indexOf('translate')==-1){
							// 		node.style.transform+=' translate('+dx+'px,'+dy+'px)';
							// 	}
							// 	else{
							// 		node.style.transform='translate('+dx+'px,'+dy+'px)';
							// 	}
							//
							// 	node.delete();
							// },700);
						}
					}
				},
				$equip:function(card){
					game.broadcast(function(player,card){
						player.$equip(card);
					},this,card);
					card.fix();
					card.style.transform='';
					card.classList.remove('drawinghidden');
					delete card._transform;
					var player=this;
					var equipNum=get.equipNum(card);
					var equipped=false;
					for(var i=0;i<player.node.equips.childNodes.length;i++){
						if(get.equipNum(player.node.equips.childNodes[i])>=equipNum){
							player.node.equips.insertBefore(card,player.node.equips.childNodes[i]);
							equipped=true;
							break;
						}
					}
					if(!equipped){
						player.node.equips.appendChild(card);
						if(_status.discarded){
							_status.discarded.remove(card);
						}
					}
					var info=get.info(card);
					if(info.skills){
						for(var i=0;i<info.skills.length;i++){
							player.addSkillTrigger(info.skills[i]);
						}
					}
					return player;
				},
				$gain:function(card,log,init){
					if(init!==false){
						game.broadcast(function(player,card,init){
							player.$gain(card,false,init);
						},this,card,init);
						if(typeof card=='number'&&card>=0){
							game.addVideo('gain',this,card);
						}
						else{
							if(get.itemtype(card)=='card'){
								card=[card];
							}
							if(get.itemtype(card)=='cards'){
								game.addVideo('gainCard',this,get.cardsInfo(card));
							}
							else{
								game.addVideo('gain',this,1);
							}
						}
					}
					if(get.itemtype(card)=='cards'){
						if(log!=false&&!_status.video){
							game.log(this,'获得了',card);
						}
						if(this.$gainmod){
							this.$gainmod(card);
						}
						else{
							for(var i=0;i<card.length;i++){
								this.$gain(card[i],false,false);
							}
						}
					}
					else if(typeof card=='number'&&card>1){
						if(log!=false&&!_status.video){
							game.log(this,'获得了'+get.cnNumber(card)+'张牌');
						}
						if(this.$gainmod){
							this.$gainmod(card);
						}
						else{
							for(var i=0;i<card;i++){
								this.$gain(1,false,false);
							}
						}
					}
					else{
						if(get.itemtype(card)=='card'&&log!=false&&!_status.video){
							game.log(this,'获得了',card);
						}
						if(this.$gainmod){
							this.$gainmod(card);
						}
						else{
							var node;
							if(get.itemtype(card)=='card'){
								// node=this.$throwordered(card.copy(),true);
								node=card.copy('thrown',false);
							}
							else{
								// node=this.$throwordered(ui.create.div('.card.thrown'),true);
								node=ui.create.div('.card.thrown');
								node.moveTo=lib.element.card.moveTo;
								node.moveDelete=lib.element.card.moveDelete;
							}
							node.fixed=true;
							node.style.left='calc(50% - 52px '+((Math.random()-0.5<0)?'+':'-')+' '+Math.random()*100+'px)';
							node.style.top='calc(50% - 52px '+((Math.random()-0.5<0)?'+':'-')+' '+Math.random()*100+'px)';
							node.style.transform='scale(0)';
							node.hide();
							ui.arena.appendChild(node);
							ui.refresh(node);
							node.show();
							node.style.transform='';

							lib.listenEnd(node);
							var player=this;
							setTimeout(function(){
								node.moveDelete(player);
							},700);
						}
					}
				},
				$gain2:function(cards,log){
					if(log===true){
						game.log(this,'获得了',cards);
					}
					game.broadcast(function(player,cards){
						player.$gain2(cards);
					},this,cards);
					if(get.itemtype(cards)=='card') cards=[cards];
					else if(get.itemtype(cards)!='cards') return;
					var list=[],list2=[];
					for(var i=0;i<cards.length;i++){
						if(cards[i].clone&&
							(cards[i].clone.parentNode==this.parentNode||
							cards[i].clone.parentNode==ui.arena)&&
							parseFloat(getComputedStyle(cards[i].clone).opacity)>0.3){
							cards[i].clone.moveDelete(this);
							list2.push(cards[i].clone);
						}
						else{
							list.push(cards[i]);
						}
					}
					if(list2.length){
						game.addVideo('gain2',this,get.cardsInfo(list2));
					}
					if(list.length){
						this.$draw(list,'nobroadcast');
						return true;
					}
				},
				$skill:function(name,type,color,avatar){
					if(typeof type!='string') type='legend';
					if(!avatar){
						this.playerfocus(1500);
						game.delay(2);
					}
					else{
						game.addVideo('playerfocus2');
						game.broadcastAll(function(){
							ui.arena.classList.add('playerfocus');
							setTimeout(function(){
								ui.arena.classList.remove('playerfocus');
							},1800)
						});
						game.delay(3);
					}
					var that=this;
					setTimeout(function(){
						game.broadcastAll(function(that,type,name,color,avatar){
							if(lib.config.animation&&!lib.config.low_performance){
								if(game.chess){
									that['$'+type+'2'](1200);
								}
								else{
									that['$'+type](1200);
								}
							}
							if(name){
								that.$fullscreenpop(name,color,avatar);
							}
						},that,type,name,color,avatar);
					},avatar?0:300);
				},
				$fire:function(){
					game.addVideo('flame',this,'fire');
					var left,top;
					if(game.chess){
						var rect=this.getBoundingClientRect();
						left=rect.left;
						top=rect.top;
					}
					else{
						left=this.getLeft();
						top=this.getTop();
					}
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-20,700,'fire');
				},
				$thunder:function(){
					game.addVideo('flame',this,'thunder');
					var left,top;
					if(game.chess){
						var rect=this.getBoundingClientRect();
						left=rect.left;
						top=rect.top;
					}
					else{
						left=this.getLeft();
						top=this.getTop();
					}
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'thunder');
				},
				$rare2:function(){
					game.addVideo('flame',this,'rare2');
					var rect=this.getBoundingClientRect();
					var left=rect.left;
					var top=rect.top+15;
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'rare');
				},
				$epic2:function(){
					game.addVideo('flame',this,'epic2');
					var rect=this.getBoundingClientRect();
					var left=rect.left;
					var top=rect.top+15;
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'epic');
				},
				$legend2:function(){
					game.addVideo('flame',this,'legend2');
					var rect=this.getBoundingClientRect();
					var left=rect.left;
					var top=rect.top+15;
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'legend');
				},
				$rare:function(time){
					time=time||700;
					game.addVideo('flame',this,'rare');
					var left,top;
					if(game.chess){
						left=this.getLeft()-ui.arena.offsetLeft;
						top=this.getTop()-ui.arena.offsetTop;
					}
					else{
						left=this.getLeft();
						top=this.getTop();
					}
					if(this.classList.contains('minskin')){
						top+=15;
					}
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,time,'rare');
				},
				$epic:function(time){
					time=time||700;
					game.addVideo('flame',this,'epic');
					var left,top;
					if(game.chess){
						left=this.getLeft()-ui.arena.offsetLeft;
						top=this.getTop()-ui.arena.offsetTop;
					}
					else{
						left=this.getLeft();
						top=this.getTop();
					}
					if(this.classList.contains('minskin')){
						top+=15;
					}
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,time,'epic');
				},
				$legend:function(time){
					time=time||700;
					game.addVideo('flame',this,'legend');
					var left,top;
					if(game.chess){
						left=this.getLeft()-ui.arena.offsetLeft;
						top=this.getTop()-ui.arena.offsetTop;
					}
					else{
						left=this.getLeft();
						top=this.getTop();
					}
					if(this.classList.contains('minskin')){
						top+=15;
					}
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,time,'legend');
				},
				$coin:function(){
					game.broadcast(function(player){
						if(!lib.config.low_performance){
							player.$coin();
						}
					},this);
					game.addVideo('flame',this,'coin');
					var left=this.getLeft()-ui.arena.offsetLeft;
					var top=this.getTop()-ui.arena.offsetTop;
					if(this.classList.contains('minskin')){
						top+=15;
					}
					top-=25;
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'coin');
				},
				$dust:function(){
					game.broadcast(function(player){
						if(!lib.config.low_performance){
							player.$dust();
						}
					},this);
					game.addVideo('flame',this,'dust');
					var left=this.getLeft()-ui.arena.offsetLeft;
					var top=this.getTop()-ui.arena.offsetTop;
					if(this.classList.contains('minskin')){
						top+=15;
					}
					top-=25;
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'dust');
				},
				$recover:function(){
					game.addVideo('flame',this,'recover');
					var left,top;
					if(game.chess){
						var rect=this.getBoundingClientRect();
						left=rect.left;
						top=rect.top;
					}
					else{
						left=this.getLeft();
						top=this.getTop();
					}
					game.animate.flame(left+this.offsetWidth/2,
						top+this.offsetHeight-30,700,'recover');
				},
				$fullscreenpop:function(str,nature,avatar,broadcast){
					if(broadcast!==false) game.broadcast(function(player,str,nature,avatar){
						player.$fullscreenpop(str,nature,avatar);
					},this,str,nature,avatar);
					game.addVideo('fullscreenpop',this,[str,nature,avatar]);
					var node=ui.create.div('.damage');
					if(avatar&&this.node){
						if(avatar=='vice'){
							if(lib.character[this.name2]){
								avatar=this.node.avatar2;
							}
						}
						else{
							if(lib.character[this.name]){
								avatar=this.node.avatar;
							}
						}
						if(!get.is.div(avatar)){
							avatar=false;
						}
					}
					else{
						avatar=false;
					}
					if(avatar){
						node.classList.add('fullscreenavatar');
						ui.create.div('',ui.create.div(node));
						// ui.create.div('',str.split('').join('<br>'),ui.create.div('.text.textbg',node));
						ui.create.div('','<div>'+str.split('').join('</div><br><div>')+'</div>',ui.create.div('.text',node));
						node.firstChild.firstChild.style.backgroundImage=avatar.style.backgroundImage;
						node.dataset.nature=nature||'unknown';
						var num=0;
						var nodes=node.lastChild.firstChild.querySelectorAll('div');
						var interval=setInterval(function(){
							if(num<nodes.length){
								nodes[num].classList.add('flashtext');
								num++;
							}
							else{
								clearInterval(interval);
							}
						},100);
					}
					else{
						avatar=false;
						node.innerHTML=str;
						node.dataset.nature=nature||'soil';
					}
					if(avatar){
						var rect1=ui.window.getBoundingClientRect();
						var rect2=this.getBoundingClientRect();
						var dx=Math.round(2*rect2.left+rect2.width-rect1.width);
						var dy=Math.round(2*rect2.top+rect2.height-rect1.height);
						node.style.transform='scale(0.5) translate('+dx+'px,'+dy+'px)';
					}
					ui.window.appendChild(node);
					ui.refresh(node);
					if(avatar){
						node.style.transform='scale(1)';
						node.style.opacity=1;
					}
					else{
						node.classList.add('damageadded');
					}
					setTimeout(function(){
						node.delete();
						node.style.transform='scale(1.5)'
					},avatar?1600:1000);
				},
				$damagepop:function(num,nature,font,nobroadcast){
					if(typeof num=='number'||typeof num=='string'){
						game.addVideo('damagepop',this,[num,nature,font]);
						if(nobroadcast!==false) game.broadcast(function(player,num,nature,font){
							player.$damagepop(num,nature,font);
						},this,num,nature,font);
						var node=ui.create.div('.damage');
						if(font){
							node.classList.add('normal-font');
						}
						if(typeof num=='number'&&num>0){
							if(num==Infinity) num='+∞'
							else num='+'+num;
						}
						else if(num==-Infinity) num='-∞';
						node.innerHTML=num;
						this.damagepopups.push(node);
						node.dataset.nature=nature||'soil';
						if(this.damagepopups.length==1){
							this.$damagepop();
						}
					}
					else if(this.damagepopups.length){
						var node=this.damagepopups[0];
						this.appendChild(node);
						ui.refresh(node);
						node.classList.add('damageadded');
						node.listenTransition(function(){
							setTimeout(function(){
								node.delete();
							},200);
						});
						// setTimeout(function(){
						// 	node.delete();
						// },500);
						var that=this;
						setTimeout(function(){
							that.damagepopups.shift();
							that.$damagepop();
						},500);
					}
				},
				$damage:function(source){
					if(get.itemtype(source)=='player'){
						game.addVideo('damage',this,source.dataset.position);
					}
					else{
						game.addVideo('damage',this);
					}
					game.broadcast(function(player,source){
						player.$damage(source);
					},this,source);
					if(source&&source!=this&&lib.config.damage_shake){
						var left,top;
						if(source.getTop()==this.getTop()){
							left=20;
							top=0;
						}
						else{
							var ratio=(source.getLeft()-this.getLeft())/(source.getTop()-this.getTop());
							left=Math.abs(20*ratio/Math.sqrt(1+ratio*ratio));
							top=Math.abs(20/Math.sqrt(1+ratio*ratio));
						}
						if(source.getLeft()-this.getLeft()>0) left=-left;
						if(source.getTop()-this.getTop()>0) top=-top;
						if(get.is.mobileMe(this)){
							if(this.classList.contains('linked')){
								this.node.avatar.style.transform='translate('+left+'px,'+top+'px) rotate(-90deg)';
								this.node.avatar2.style.transform='translate('+left+'px,'+top+'px) rotate(-90deg)';
							}
							else{
								this.node.avatar.style.transform='translate('+left+'px,'+top+'px)';
								this.node.avatar2.style.transform='translate('+left+'px,'+top+'px)';
							}
						}
						else if(this.classList.contains('linked')&&get.is.newLayout()){
							this.style.transform='translate('+left+'px,'+top+'px) rotate(-90deg)';
						}
						else if(this._chesstransform){
							this.style.transform='translate('+(left+this._chesstransform[0])+'px,'+(top+this._chesstransform[1])+'px)';
						}
						else{
							this.style.transform='translate('+left+'px,'+top+'px)';
						}
					}
					else{
						var zoom1=0.9,zoom2=0.95;
						if(arguments[1]=='phase'){
							zoom1=1.05;
							zoom2=1.05;
						}
						if(get.is.mobileMe(this)){
							if(this.classList.contains('linked')){
								this.node.avatar.style.transform='scale('+zoom1+') rotate(-90deg)';
								this.node.avatar2.style.transform='scale('+zoom1+') rotate(-90deg)';
							}
							else{
								this.node.avatar.style.transform='scale('+zoom1+')';
								this.node.avatar2.style.transform='scale('+zoom1+')';
							}
						}
						else if(this.classList.contains('linked')&&get.is.newLayout()){
							this.style.transform='scale('+zoom2+') rotate(-90deg)';
						}
						else if(game.chess&&this._chesstransform){
							this.style.transform='translate('+this._chesstransform[0]+'px,'+this._chesstransform[1]+'px) scale('+zoom2+')';
						}
						else{
							this.style.transform='scale('+zoom2+')';
						}
					}
					this.queue();
				},
				$die:function(){
					game.addVideo('die',this);
					game.broadcast(function(player){
						player.$die();
					},this);
					if(lib.config.die_move!='off'){
						this.$dieflip(lib.config.die_move);
					}
					if(lib.element.player.$dieAfter){
						lib.element.player.$dieAfter.call(this);
					}
				},
				$dieflip:function(type){
					var top0=ui.window.offsetHeight/2;
					var left0=ui.window.offsetWidth/2;
					var ratio=(left0-this.getLeft())/(top0-this.getTop());
					var left=Math.abs(50*ratio/Math.sqrt(1+ratio*ratio));
					var top=Math.abs(50/Math.sqrt(1+ratio*ratio));
					if(left0-this.getLeft()>0) left=-left;
					if(top0-this.getTop()>0) top=-top;
					if(get.is.mobileMe(this)){
						left=-Math.random()*5-10;
						top=Math.random()*5+10;
					}
					if(this._chesstransform){
						left+=this._chesstransform[0];
						top+=this._chesstransform[1];
					}
					var transform='translate('+left+'px,'+top+'px) '+
					'rotate('+(Math.random()*20-10)+'deg) ';
					if(type=='flip'){
						if(game.layout=='long'||game.layout=='long2'){
							transform+='rotateY(180deg)';
						}
						else{
							transform+=((Math.random()-0.5<0)?'rotateX(180deg)':'rotateY(180deg)');
						}
					}
					if(get.is.mobileMe(this)){
						this.node.avatar.style.transform=transform;
						this.node.avatar2.style.transform=transform;
						this.style.transform='';
					}
					else{
						this.node.avatar.style.transform='';
						this.node.avatar2.style.transform='';
						this.style.transform=transform;
					}
					this.queue(false);
				},
				$phaseJudge:function(card){
					game.addVideo('phaseJudge',this,get.cardInfo(card));
					var player=this;
					var clone=player.$throw(card);
					if(lib.config.low_performance&&card&&card.clone){
						var waitingForTransition=get.time();
						_status.waitingForTransition=waitingForTransition;
						card.clone.listenTransition(function(){
							if(_status.waitingForTransition==waitingForTransition&&_status.paused){
								game.resume();
							}
						});
						game.pause();
					}
					else{
						game.delay();
					}
				}
			},
			card:{
				hasNature:function(nature,player){
					return game.hasNature(this,nature,player);
				},
				//只针对【杀】起效果
				addNature:function(nature){
					let natures=[];
					if(!this.nature) this.nature='';
					else{
						natures.addArray(get.natureList(this.nature));
					}
					natures.addArray(get.natureList(nature));
					this.nature=get.nature(natures);
					this.classList.add(nature);
					let str=get.translation(this.nature)+'杀';
					this.node.name.innerText=str;
					let name=get.name(this,false);
					do{
						if(name=='sha'){
							let _bg;
							for(const n of natures) if(lib.natureBg.has(n)) _bg=n;
							if(_bg){
								this.node.image.setBackgroundImage(lib.natureBg.get(_bg));
								break;
							}
						}
						this.node.image.setBackgroundImage('image/card/'+name+'.png');
					}
					while(0);
					return this.nature;
				},
				removeNature:function(nature){
					if(!this.nature) return;
					let natures=get.natureList(this.nature);
					natures.remove(nature);
					if(!natures.length) delete this.nature;
					else this.nature=get.nature(natures);
					this.classList.remove(nature);
					let str=get.translation(this.nature)+'杀';
					this.node.name.innerText=str;
					let name=get.name(this,false);
					do{
						if(name=='sha'){
							let _bg;
							for(const n of natures) if(lib.natureBg.has(n)) _bg=n;
							if(_bg){
								this.node.image.setBackgroundImage(lib.natureBg.get(_bg));
								break;
							}
						}
						this.node.image.setBackgroundImage('image/card/'+name+'.png');
					}
					while(0);
					return this.nature;
				},
				addGaintag:function(gaintag){
					if(Array.isArray(gaintag)) this.gaintag=gaintag.slice(0);
					else this.gaintag.add(gaintag);
					var str='';
					for(var gi=0;gi<this.gaintag.length;gi++){
						var translate=get.translation(this.gaintag[gi]);
						if(translate!='invisible'){
							str+=translate;
							if(gi<this.gaintag.length-1) str+=' ';
						}
					}
					this.node.gaintag.innerHTML=str;
				},
				removeGaintag:function(tag){
					if(tag===true){
						if(this.gaintag&&this.gaintag.length||this.node.gaintag.innerHTML.length) this.addGaintag([]);
					}
					else if(this.hasGaintag(tag)){
						this.gaintag.remove(tag);
						this.addGaintag(this.gaintag);
					}
				},
				hasGaintag:function(tag){
					return this.gaintag&&this.gaintag.contains(tag);
				},
				init:function(card){
					if(Array.isArray(card)){
						if(card[2]=='huosha'){
							card[2]='sha';
							card[3]='fire';
						}
						else if(card[2]=='leisha'){
							card[2]='sha';
							card[3]='thunder';
						}
						// else if(card[2]=='kamisha'){
						// 	card[2]='sha';
						// 	card[3]='kami';
						// }
						// else if(card[2]=='icesha'){
						// 	card[2]='sha';
						// 	card[3]='ice';
						// }
						else if(card[2]=='cisha'){
							card[2]='sha';
							card[3]='stab';
						}
						else if(card[2].length>3){
							let prefix=card[2].slice(0,card[2].lastIndexOf('sha'));
							if(lib.nature.has(prefix)){
								if(prefix.length+3==card[2].length){
									card[2]='sha';
									card[3]=prefix;
								}
							}
							if(card[2].startsWith('sha_')){
								let suffix=card[2].slice(4);
								let natureList=suffix.split('_');
								card[2]='sha';
								card[3]=get.nature(natureList);
							}
						}
					}
					else if(typeof card=='object'){
						card=[card.suit,card.number,card.name,card.nature];
					}
					var cardnum=card[1]||'';
					if(parseInt(cardnum)==cardnum) cardnum=parseInt(cardnum);
					if(cardnum>0&&cardnum<14){
						cardnum=['A','2','3','4','5','6','7','8','9','10','J','Q','K'][cardnum-1];
					}
					if(!lib.card[card[2]]){
						lib.card[card[2]]={};
					}
					var info=lib.card[card[2]];
					if(info.global&&!this.classList.contains('button')){
						if(Array.isArray(info.global)){
							while(info.global.length){
								game.addGlobalSkill(info.global.shift());
							}
						}
						else if(typeof info.global=='string'){
							game.addGlobalSkill(info.global);
						}
						delete info.global;
					}
					if(this.name){
						this.classList.remove('epic');
						this.classList.remove('legend');
						this.classList.remove('gold');
						this.classList.remove('unique');
						this.style.background='';
						var subtype=get.subtype(this);
						if(subtype){
							this.classList.remove(subtype);
						}
					}
					if(info.epic){
						this.classList.add('epic');
					}
					else if(info.legend){
						this.classList.add('legend');
					}
					else if(info.gold){
						this.classList.add('gold');
					}
					else if(info.unique){
						this.classList.add('unique');
					}
					var bg=card[2];
					if(info.cardimage){
						bg=info.cardimage;
					}
					var img=lib.card[bg].image;
					if(img){
						if(img.startsWith('db:')){
							img=img.slice(3);
						}
						else if(!img.startsWith('ext:')){
							img=null;
						}
					}
					this.classList.remove('fullskin');
					this.classList.remove('fullimage');
					this.classList.remove('fullborder');
					this.dataset.cardName=card[2];
					this.dataset.cardType=info.type||'';
					this.dataset.cardSubype=info.subtype||'';
					this.dataset.cardMultitarget=info.multitarget?'1':'0';
					this.node.name.dataset.nature='';
					this.node.info.classList.remove('red');
					if(!lib.config.hide_card_image&&lib.card[bg].fullskin){
						this.classList.add('fullskin');
						if(img){
							if(img.startsWith('ext:')){
								this.node.image.setBackgroundImage(img.replace(/^ext:/,'extension/'));
							}
							else{
								this.node.image.setBackgroundDB(img);
							}
						}
						else{
							if(lib.card[bg].modeimage){
								this.node.image.setBackgroundImage('image/mode/'+lib.card[bg].modeimage+'/card/'+bg+'.png');
							}
							else{
								do{
									let nature=card[3];
									if(bg=='sha'&&typeof nature=='string'){
										let natures=get.natureList(nature),_bg;
										for(const n of natures) if(lib.natureBg.has(n)) _bg=n;
										if(_bg){
											this.node.image.setBackgroundImage(lib.natureBg.get(_bg));
											break;
										}
									}
									this.node.image.setBackgroundImage('image/card/'+bg+'.png');
								}
								while(0);
							}
						}
					}
					else if(lib.card[bg].image=='background'){
						if(card[3]) this.node.background.setBackground(bg+'_'+get.natureList(card[3])[0],'card');
						else this.node.background.setBackground(bg,'card');
					}
					else if(lib.card[bg].fullimage){
						this.classList.add('fullimage');
						if(img){
							if(img.startsWith('ext:')){
								this.setBackgroundImage(img.replace(/^ext:/,'extension/'));
								this.style.backgroundSize='cover';
							}
							else{
								this.setBackgroundDB(img);
							}
						}
						else if(lib.card[bg].image){
							if(lib.card[bg].image.startsWith('character:')){
								this.setBackground(lib.card[bg].image.slice(10),'character');
							}
							else{
								this.setBackground(lib.card[bg].image);
							}
						}
						else{
							var cardPack=lib.cardPack['mode_'+get.mode()];
							if(Array.isArray(cardPack)&&cardPack.contains(bg)){
								this.setBackground('mode/'+get.mode()+'/card/'+bg);
							}
							else{
								this.setBackground('card/'+bg);
							}
						}
					}
					else if(lib.card[bg].fullborder){
						this.classList.add('fullborder');
						if(lib.card[bg].fullborder=='gold'){
							this.node.name.dataset.nature='metalmm';
						}
						else if(lib.card[bg].fullborder=='silver'){
							this.node.name.dataset.nature='watermm';
						}
						if(!this.node.avatar){
							this.node.avatar=ui.create.div('.cardavatar');
							this.insertBefore(this.node.avatar,this.firstChild);
						}
						if(!this.node.framebg){
							this.node.framebg=ui.create.div('.cardframebg');
							this.node.framebg.dataset.auto=lib.card[bg].fullborder;
							this.insertBefore(this.node.framebg,this.firstChild);
						}
						if(img){
							if(img.startsWith('ext:')){
								this.node.avatar.setBackgroundImage(img.replace(/^ext:/,'extension/'));
								this.node.avatar.style.backgroundSize='cover';
							}
							else{
								this.node.avatar.setBackgroundDB(img);
							}
						}
						else if(lib.card[bg].image){
							if(lib.card[bg].image.startsWith('character:')){
								this.node.avatar.setBackground(lib.card[bg].image.slice(10),'character');
							}
							else{
								this.node.avatar.setBackground(lib.card[bg].image);
							}
						}
						else{
							var cardPack=lib.cardPack['mode_'+get.mode()];
							if(Array.isArray(cardPack)&&cardPack.contains(bg)){
								this.node.avatar.setBackground('mode/'+get.mode()+'/card/'+bg);
							}
							else{
								this.node.avatar.setBackground('card/'+bg);
							}
						}
					}
					else if(lib.card[bg].image=='card'){
						if(card[3]) this.setBackground(bg+'_'+get.natureList(card[3])[0],'card');
						else this.setBackground(bg,'card');
					}
					else if(typeof lib.card[bg].image=='string'&&!lib.card[bg].fullskin){
						if(img){
							if(img.startsWith('ext:')){
								this.setBackgroundImage(img.replace(/^ext:/,'extension/'));
								this.style.backgroundSize='cover';
							}
							else{
								this.setBackgroundDB(img);
							}
						}
						else{
							this.setBackground(lib.card[bg].image);
						}
					}
					else{
						this.node.background.innerHTML=lib.translate[bg+'_cbg']||lib.translate[bg+'_bg']||get.translation(bg)[0];
						// this.node.background.style.fontFamily=lib.config.card_font;
						if(this.node.background.innerHTML.length>1) this.node.background.classList.add('tight');
						else this.node.background.classList.remove('tight');
					}
					if(!lib.card[bg].fullborder&&this.node.avatar&&this.node.framebg){
						this.node.avatar.remove();
						this.node.framebg.remove();
						delete this.node.avatar;
						delete this.node.framebg;
					}
					if(info.noname&&!this.classList.contains('button')){
						this.node.name.style.display='none';
					}
					if(info.color){
						this.style.color=info.color;
					}
					if(info.textShadow){
						this.style.textShadow=info.textShadow;
					}
					if(info.opacity){
						this.node.info.style.opacity=info.opacity;
						this.node.name.style.opacity=info.opacity;
					}
					if(info.modinfo){
						this.node.info.innerHTML=info.modinfo;
					}
					else{
						this.node.info.innerHTML=get.translation(card[0])+'<span style="font-family:xinwei"> </span><span style="font-family:xinwei">'+cardnum+'</span>';
					}
					if(info.addinfo){
						if(!this.node.addinfo){
							this.node.addinfo=ui.create.div('.range',this);
						}
						this.node.addinfo.innerHTML=info.addinfo;
					}
					else if(this.node.addinfo){
						this.node.addinfo.remove();
						delete this.node.addinfo;
					}
					if(card[0]=='heart'||card[0]=='diamond'){
						this.node.info.classList.add('red');
					}
					this.node.image.className='image';
					var name=get.translation(card[2]);
					if(card[2]=='sha'){
						name='';
						let nature=card[3];
						if(nature){
							let natures=get.natureList(nature);
							natures.sort(lib.sort.nature);
							for(let nature of natures){
								name+=lib.translate['nature_'+nature]||lib.translate[nature]||'';
								if(nature!='stab') this.node.image.classList.add(nature);
							}
						}
						name+='杀';
					}
					this.node.name.innerHTML=name;
					if(name.length>=5){
						this.node.name.classList.add('long');
						if(name.length>=7){
							this.node.name.classList.add('longlong');
						}
					}
					this.node.name2.innerHTML=get.translation(card[0])+cardnum+' '+name;
					this.suit=card[0];
					this.number=parseInt(card[1])||0;
					this.name=card[2];
					this.classList.add('card');
					if(card[3]){
						let natures=get.natureList(card[3]);
						natures.forEach(n=>{if(n) this.classList.add(n)});
						this.nature=natures.filter(n=>lib.nature.has(n)).sort(lib.sort.nature).join(lib.natureSeparator);
					}
					else if(this.nature){
						this.classList.remove(this.nature);
						delete this.nature;
					}
					if(info.subtype) this.classList.add(info.subtype);
					if(this.inits){
						for(var i=0;i<lib.element.card.inits.length;i++){
							lib.element.card.inits[i](this);
						}
					}
					if(typeof info.init=='function') info.init();
					this.node.range.innerHTML='';
					switch(get.subtype(this)){
						case 'equip1':
							var added=false;
							if(lib.card[this.name]&&lib.card[this.name].distance){
								var dist=lib.card[this.name].distance;
								if(dist.attackFrom){
									added=true;
									this.node.range.innerHTML='范围: '+(-dist.attackFrom+1);
								}
							}
							if(!added){
								this.node.range.innerHTML='范围: 1';
							}
							break;
						case 'equip3':
						if(info.distance&&info.distance.globalTo){
							this.node.range.innerHTML='防御: '+info.distance.globalTo;
							this.node.name2.innerHTML+='+';
						}
						break;
						case 'equip4':
						if(info.distance&&info.distance.globalFrom){
							this.node.range.innerHTML='进攻: '+(-info.distance.globalFrom);
							this.node.name2.innerHTML+='-';
						}
						break;
					}
					if(_status.connectMode&&!game.online&&lib.cardOL&&!this.cardid){
						this.cardid=get.id();
						lib.cardOL[this.cardid]=this;
					}
					if(!_status.connectMode&&!_status.video){
						this.cardid=get.id();
					}
					var tags=[];
					if(Array.isArray(card[4])){
						tags.addArray(card[4]);
					}
					if(this.cardid){
						if(!_status.cardtag){
							_status.cardtag={};
						}
						for(var i in _status.cardtag){
							if(_status.cardtag[i].contains(this.cardid)){
								tags.add(i);
							}
						}
						if(tags.length){
							var tagstr=' <span class="cardtag">';
							for(var i=0;i<tags.length;i++){
								var tag=tags[i];
								if(!_status.cardtag[tag]){
									_status.cardtag[tag]=[];
								}
								_status.cardtag[tag].add(this.cardid);
								tagstr+=lib.translate[tag+'_tag'];
								//if(i<tags.length-1) tagstr+=' ';
							}
							tagstr+='</span>';
							this.node.range.innerHTML+=tagstr;
						}
					}
					return this;
				},
				updateTransform:function(bool,delay){
					if(delay){
						var that=this;
						setTimeout(function(){
							that.updateTransform(that.classList.contains('selected'));
						},delay);
					}
					else{
						if(_status.event.player!=game.me) return;
						if(this._transform&&this.parentNode&&this.parentNode.parentNode&&
							this.parentNode.parentNode.parentNode==ui.me&&
							(!_status.mousedown||_status.mouseleft)&&
							(!this.parentNode.parentNode.classList.contains('scrollh')||(game.layout=='long2'||game.layout=='nova'))){
							if(bool){
								this.style.transform=this._transform+' translateY(-20px)';
							}
							else{
								this.style.transform=this._transform||'';
							}
						}
					}
				},
				aiexclude:function(){
					_status.event._aiexclude.add(this);
				},
				getSource:function(name){
					if(this.name==name) return true;
					var info=lib.card[this.name];
					if(info&&Array.isArray(info.source)){
						return info.source.contains(name);
					}
					return false;
				},
				moveDelete:function(player){
					this.fixed=true;
					if(!this._listeningEnd||this._transitionEnded){
						this.moveTo(player);
						var that=this;
						setTimeout(function(){
							that.delete();
						},200);
					}
					else{
						this._onEndMoveDelete=player;
					}
				},
				moveTo:function(player){
					this.fixed=true;
					var dx,dy;
					if(this.classList.contains('center')){
						var nx=[50,-52];
						var ny=[50,-52];
						nx=nx[0]*ui.arena.offsetWidth/100+nx[1];
						ny=ny[0]*ui.arena.offsetHeight/100+ny[1];
						dx=player.getLeft()+player.offsetWidth/2-52-nx;
						dy=player.getTop()+player.offsetHeight/2-52-ny;
					}
					else{
						this.style.left=this.offsetLeft+'px';
						this.style.top=this.offsetTop+'px';

						dx=player.getLeft()+player.offsetWidth/2-52-this.offsetLeft;
						dy=player.getTop()+player.offsetHeight/2-52-this.offsetTop;
					}
					if(get.is.mobileMe(player)){
						dx+=get.cardOffset();
						if(ui.arena.classList.contains('oblongcard')){
							dy-=16;
						}
					}


					if(this.style.transform&&this.style.transform!='none'&&this.style.transform.indexOf('translate')==-1){
						this.style.transform+=' translate('+dx+'px,'+dy+'px)';
					}
					else{
						this.style.transform='translate('+dx+'px,'+dy+'px)';
					}
					return this;
				},
				copy:function(){
					var node=this.cloneNode(true);
					node.style.transform='';
					node.name=this.name;
					node.suit=this.suit;
					node.number=this.number;
					node.classList.remove('hidden');
					node.classList.remove('start');
					node.classList.remove('thrown');
					node.classList.remove('selectable');
					node.classList.remove('selected');
					node.classList.remove('removing');
					node.classList.remove('drawinghidden');
					node.classList.remove('glows');
					node.node={
						name:node.querySelector('.name'),
						info:node.querySelector('.info'),
						intro:node.querySelector('.intro'),
						background:node.querySelector('.background'),
						image:node.querySelector('.image'),
						gaintag:node.querySelector('.gaintag'),
					}
					node.node.gaintag.innerHTML='';
					var clone=true;
					var position;
					for(var i=0;i<arguments.length;i++){
						if(typeof arguments[i]=='string') node.classList.add(arguments[i]);
						else if(get.objtype(arguments[i])=='div') position=arguments[i];
						else if(typeof arguments[i]=='boolean') clone=arguments[i];
					}
					node.moveTo=lib.element.card.moveTo;
					node.moveDelete=lib.element.card.moveDelete;
					if(clone) this.clone=node;
					if(position) position.appendChild(node);
					return node;
				},
				uncheck:function(skill){
					if(skill) this._uncheck.add(skill);
					this.classList.add('uncheck');
				},
				recheck:function(skill){
					if(skill) this._uncheck.remove(skill);
					else this._uncheck.length=0;
					if(this._uncheck.length==0) this.classList.remove('uncheck');
				},
				discard:function(bool){
					if(!this.destroyed){
						ui.discardPile.appendChild(this);
					}
					this.fix();
					this.classList.remove('glow');
					if(bool===false){
						ui.cardPile.insertBefore(this,ui.cardPile.childNodes[Math.floor(Math.random()*ui.cardPile.childNodes.length)]);
					}
					else{
						if(_status.discarded){
							_status.discarded.add(this);
						}
					}
				},
				hasTag:function(tag){
					if(this.cardid&&_status.cardtag&&_status.cardtag[tag]&&_status.cardtag[tag].contains(this.cardid)){
						return true;
					}
					return false;
				},
				hasPosition:function(){
					return ['h','e','j','s','x'].contains(get.position(this));
				},
				isInPile:function(){
					return ['c','d'].contains(get.position(this));
				}
			},
			button:{
				exclude:function(){
					if(_status.event.excludeButton==undefined){
						_status.event.excludeButton=[];
					}
					_status.event.excludeButton.add(this);
				}
			},
			event:{
				changeToZero:function(){
					this.num=0;
					this.numFixed=true;
				},
				finish:function(){
					this.finished=true;
				},
				putStepCache:function(key,value){
					if(!this._stepCache){
						this._stepCache = {};
					}
					this._stepCache[key] = value;
				},
				getStepCache:function(key){
					if(!this._stepCache)return undefined;
					return this._stepCache[key];
				},
				clearStepCache:function(key){
					if(key !==  undefined && key !== null){
						delete this._stepCache[key];
					}
					delete this._stepCache;
				},
				callFuncUseStepCache:function(prefix,func,params){
					if(typeof func != 'function')return;
					if(_status.closeStepCache)return func.apply(null,params);
					var cacheKey = "["+prefix+"]"+get.paramToCacheKey.apply(null,params);
					var ret = this.getStepCache(cacheKey);
					if(ret === undefined || ret === null){
						ret = func.apply(null,params);
						this.putStepCache(cacheKey,ret);
					}
					return ret;
				},
				putTempCache:function(key1,key2,value){
					if(!this._tempCache){
						this._tempCache = {};
					}
					if(!this._tempCache[key1]){
						this._tempCache[key1] = {};
					}
					this._tempCache[key1][key2] = value;
					return value;
				},
				getTempCache:function(key1,key2){
					if(!this._tempCache){
						return undefined;
					}
					if(!this._tempCache[key1]){
						return undefined;
					}
					return this._tempCache[key1][key2];
				},
				cancel:function(arg1,arg2,notrigger){
					this.untrigger(arg1,arg2);
					this.finish();
					if(notrigger!='notrigger'){
						this.trigger(this.name+'Cancelled');
						if(this.player&&lib.phaseName.contains(this.name)) this.player.getHistory('skipped').add(this.name)}
				},
				neutralize:function(event){
					this.untrigger();
					this.finish();
					this._neutralized=true;
					this.trigger('eventNeutralized');
					this._neutralize_event=event||_status.event;
				},
				unneutralize:function(){
					this.untrigger();
					delete this._neutralized;
					delete this.finished;
					if(this.type=='card'&&this.card&&this.name=='sha') this.directHit=true;
				},
				goto:function(step){
					this.step=step-1;
				},
				redo:function(){
					this.step--;
				},
				setHiddenSkill:function(skill){
					if(!this.player) return this;
					var hidden=this.player.hiddenSkills.slice(0);
					game.expandSkills(hidden);
					if(hidden.contains(skill)) this.set('hsskill',skill);
					return this;
				},
				set:function(key,value){
					if(arguments.length==1&&Array.isArray(arguments[0])){
						for(var i=0;i<arguments[0].length;i++){
							if(Array.isArray(arguments[0][i])){
								this.set(arguments[0][i][0],arguments[0][i][1]);
							}
						}
					}
					else{
						if(typeof key!='string'){
							console.log('warning: using non-string object as event key');
							console.log(key,value);
							console.log(_status.event);
						}
						this[key]=value;
						this._set.push([key,value]);
					}
					return this;
				},
				setContent:function(item){
					switch(typeof item){
						case "object":
						case "function":
							this.content=lib.init.parsex(item);
							break;
						default:
							try{
								if(!lib.element.content[item]._parsed){
									lib.element.content[item]=lib.init.parsex(lib.element.content[item]);
									lib.element.content[item]._parsed=true;
								}
							}
							catch(_){
								throw new Error(`Content ${item} may not exist.\nlib.element.content[${item}] = ${lib.element.content[item]}`);
							}
							this.content=lib.element.content[item];
							break;
					}
					return this;
				},
				getLogv:function(){
					for(var i=1;i<=3;i++){
						var event=this.getParent(i);
						if(event&&event.logvid) return event.logvid;
					}
					return null;
				},
				send:function(){
					this.player.send(function(name,args,set,event,skills){
						game.me.applySkills(skills);
						var next=game.me[name].apply(game.me,args);
						for(var i=0;i<set.length;i++){
							next.set(set[i][0],set[i][1]);
						}
						if(next._backupevent){
							next.backup(next._backupevent);
						}
						next._modparent=event;
						game.resume();
					},this.name,this._args||[],this._set,
					get.stringifiedResult(this.parent),get.skillState(this.player));
					this.player.wait();
					game.pause();
				},
				resume:function(){
					delete this._cardChoice;
					delete this._targetChoice;
					delete this._skillChoice;
				},
				getParent:function(level,forced){
					var parent,historys=[];
					if(this._modparent&&game.online){
						parent=this._modparent;
					}
					else{
						parent=this.parent;
					}
					var toreturn={};
					if(typeof level=='string'&&forced==true){
						toreturn=null;
					}
					if(!parent) return toreturn;
					if(typeof level=='number'){
						for(var i=1;i<level;i++){
							if(!parent) return toreturn;
							parent=parent.parent;
						}
					}
					else if(typeof level=='string'){
						while(true){
							if(!parent) return toreturn;
							historys.push(parent);
							if(parent.name==level) return parent;
							parent=parent.parent;
							if(historys.contains(parent)) return toreturn;
						}
						if(!parent) return toreturn;
					}
					if(toreturn===null){
						return null;
					}
					return parent;
				},
				getTrigger:function(){
					return this.getParent()._trigger;
				},
				getRand:function(name){
					if(name){
						if(!this._rand_map) this._rand_map={};
						if(!this._rand_map[name]) this._rand_map[name]=Math.random();
						return this._rand_map[name];
					}
					if(!this._rand) this._rand=Math.random();
					return this._rand;
				},
				insert:function(func,map){
					var next=game.createEvent(this.name+'Inserted',false,this);
					next.setContent(func);
					for(var i in map){
						next.set(i,map[i]);
					}
					return next;
				},
				insertAfter:function(func,map){
					var next=game.createEvent(this.name+'Inserted',false,{next:[]});
					this.after.push(next);
					next.setContent(func);
					for(var i in map){
						next.set(i,map[i]);
					}
					return next;
				},
				backup:function(skill){
					this._backup={
						filterButton:this.filterButton,
						selectButton:this.selectButton,
						filterTarget:this.filterTarget,
						selectTarget:this.selectTarget,
						filterCard:this.filterCard,
						selectCard:this.selectCard,
						position:this.position,
						forced:this.forced,
						fakeforce:this.fakeforce,
						_aiexclude:this._aiexclude,
						complexSelect:this.complexSelect,
						complexCard:this.complexCard,
						complexTarget:this.complexTarget,
						_cardChoice:this._cardChoice,
						_targetChoice:this._targetChoice,
						_skillChoice:this._skillChoice,
						ai1:this.ai1,
						ai2:this.ai2,
						filterOk:this.filterOk,
					}
					if(skill){
						var info=get.info(skill);
						this.skill=skill;
						this._aiexclude=[];
						if(typeof info.viewAs=='function'){
							if(info.filterButton!=undefined) this.filterButton=get.filter(info.filterButton);
							if(info.selectButton!=undefined) this.selectButton=info.selectButton;
							if(info.filterTarget!=undefined) this.filterTarget=get.filter(info.filterTarget);
							if(info.selectTarget!=undefined) this.selectTarget=info.selectTarget;
							if(info.filterCard!=undefined){
								if(info.ignoreMod) this.ignoreMod=true;
								this.filterCard2=get.filter(info.filterCard);
								this.filterCard=function(card,player,event){
									var evt=event||_status.event;
									if(!evt.ignoreMod&&player){
										var mod=game.checkMod(card,player,'unchanged','cardEnabled2',player);
										if(mod!='unchanged') return mod;
									}
									return get.filter(evt.filterCard2).apply(this,arguments);
								};
							}
							if(info.filterOk==undefined){
								this.filterOk=function(){
									var evt=_status.event;
									var card=get.card(),player=get.player();
									var filter=evt._backup.filterCard;
									if(filter&&!filter(card,player,evt)) return false;
									if(evt._backup.filterOk) return evt._backup.filterOk();
									return true;
								};
							}
							else this.filterOk=info.filterOk;
							if(info.selectCard!=undefined) this.selectCard=info.selectCard;
							if(info.position!=undefined) this.position=info.position;
							//if(info.forced!=undefined) this.forced=info.forced;
							if(info.complexSelect!=undefined) this.complexSelect=info.complexSelect;
							if(info.complexCard!=undefined) this.complexCard=info.complexCard;
							if(info.complexTarget!=undefined) this.complexTarget=info.complexTarget;
							if(info.ai1!=undefined) this.ai1=info.ai1;
							if(info.ai2!=undefined) this.ai2=info.ai2;
						}
						else if(info.viewAs){
							if(info.filterButton!=undefined) this.filterButton=get.filter(info.filterButton);
							if(info.selectButton!=undefined) this.selectButton=info.selectButton;
							if(info.filterTarget!=undefined) this.filterTarget=get.filter(info.filterTarget);
							if(info.selectTarget!=undefined) this.selectTarget=info.selectTarget;
							if(info.filterCard!=undefined){
								if(info.ignoreMod) this.ignoreMod=true;
								this.filterCard2=get.filter(info.filterCard);
								this.filterCard=function(card,player,event){
									var evt=event||_status.event;
									if(!evt.ignoreMod&&player){
										var mod=game.checkMod(card,player,'unchanged','cardEnabled2',player);
										if(mod!='unchanged') return mod;
									}
									return get.filter(evt.filterCard2).apply(this,arguments);
								};
							}
							if(info.filterOk==undefined){
								this.filterOk=function(){
									var evt=_status.event;
									var card=get.card(),player=get.player();
									var filter=evt._backup.filterCard;
									if(filter&&!filter(card,player,evt)) return false;
									if(evt._backup.filterOk) return evt._backup.filterOk()
									return true;
								};
							}
							else this.filterOk=info.filterOk;
							if(info.selectCard!=undefined) this.selectCard=info.selectCard;
							if(info.position!=undefined) this.position=info.position;
							//if(info.forced!=undefined) this.forced=info.forced;
							if(info.complexSelect!=undefined) this.complexSelect=info.complexSelect;
							if(info.complexCard!=undefined) this.complexCard=info.complexCard;
							if(info.complexTarget!=undefined) this.complexTarget=info.complexTarget;
							if(info.ai1!=undefined) this.ai1=info.ai1;
							if(info.ai2!=undefined) this.ai2=info.ai2;
						}
						else{
							this.filterButton=info.filterButton?get.filter(info.filterButton):undefined;
							this.selectButton=info.selectButton;
							this.filterTarget=info.filterTarget?get.filter(info.filterTarget):undefined;
							this.selectTarget=info.selectTarget;
							this.filterCard=info.filterCard?get.filter(info.filterCard):undefined;
							this.selectCard=info.selectCard;
							this.position=info.position;
							//this.forced=info.forced;
							this.complexSelect=info.complexSelect;
							this.complexCard=info.complexCard;
							this.complexTarget=info.complexTarget;
							if(info.ai1!=undefined) this.ai1=info.ai1;
							if(info.ai2!=undefined) this.ai2=info.ai2;
							this.filterOk=info.filterOk;
						}
						delete this.fakeforce;
					}
					delete this._cardChoice;
					delete this._targetChoice;
					delete this._skillChoice;
				},
				restore:function(){
					if(this._backup){
						this.filterButton=this._backup.filterButton;
						this.selectButton=this._backup.selectButton;
						this.filterTarget=this._backup.filterTarget;
						this.selectTarget=this._backup.selectTarget;
						this.filterCard=this._backup.filterCard;
						this.selectCard=this._backup.selectCard;
						this.position=this._backup.position;
						this.forced=this._backup.forced;
						this.fakeforce=this._backup.fakeforce;
						this._aiexclude=this._backup._aiexclude;
						this.complexSelect=this._backup.complexSelect;
						this.complexCard=this._backup.complexCard;
						this.complexTarget=this._backup.complexTarget;
						this.ai1=this._backup.ai1;
						this.ai2=this._backup.ai2;
						this._cardChoice=this._backup._cardChoice;
						this._targetChoice=this._backup._targetChoice;
						this._skillChoice=this._backup._skillChoice;
						this.filterOk=this._backup.filterOk;
					}
					delete this.skill;
					delete this.ignoreMod;
					delete this.filterCard2;
				},
				isMine:function(){
					return (this.player&&this.player==game.me&&!_status.auto&&!this.player.isMad()&&!game.notMe);
				},
				isOnline:function(){
					return (this.player&&this.player.isOnline());
				},
				notLink:function(){
					return this.getParent().name!='_lianhuan'&&this.getParent().name!='_lianhuan2';
				},
				isPhaseUsing:function(player){
					var evt=this.getParent('phaseUse');
					if(!evt||evt.name!='phaseUse') return false;
					return !player||player==evt.player;
				},
				addTrigger:function(skill,player){
					if(!player) return;
					var evt=this;
					while(true){
						var evt=evt.getParent('arrangeTrigger');
						if(!evt||evt.name!='arrangeTrigger'||!evt.map) return;
						if(typeof skill=='string') skill=[skill];
						game.expandSkills(skill);
						var filter=function(content){
							if(typeof content=='string') return content==triggername;
							return content.contains(triggername);
						};
						var trigger=evt._trigger;
						var triggername=evt.triggername;
						var map=false;
						if(evt.doing&&evt.doing.player==player) map=evt.doing;
						else{
							for(var i=0;i<evt.map.length;i++){
								if(evt.map[i].player==player){map=evt.map[i];break;}
							}
						}
						if(!map) return;
						var func=function(skillx){
							var info=lib.skill[skillx];
							var bool=false;
							for(var i in info.trigger){
								if(filter(info.trigger[i])){bool=true;break}
							}
							if(!bool) return;
							var priority=get.priority(skill);
							var toadd=[skillx,player,priority];
							if(map.list2){
								for(var i=0;i<map.list2.length;i++){
									if(map.list2[i][0]==toadd[0]&&map.list2[i][1]==toadd[1]) return;
								}
							};
							for(var i=0;i<map.list.length;i++){
								if(map.list[i][0]==toadd[0]&&map.list[i][1]==toadd[1]) return;
							}
							map.list.add(toadd);
							map.list.sort(function(a,b){
								return b[2]-a[2];
							});
						}
						for(var j=0;j<skill.length;j++){
							func(skill[j]);
						}
					}
				},
				trigger:function(name){
					if(_status.video) return;
					if((this.name==='gain'||this.name==='lose')&&!_status.gameDrawed) return;
					if(name==='gameDrawEnd') _status.gameDrawed=true;
					if(name==='gameStart'){
						lib.announce.publish('gameStart',{});
						if(_status.brawl&&_status.brawl.gameStart){
							_status.brawl.gameStart();
						}
						if(lib.config.show_cardpile){
							ui.cardPileButton.style.display='';
						}
						_status.gameStarted=true;
						game.showHistory();
					}
					if(!lib.hookmap[name]&&!lib.config.compatiblemode) return;
					if(!game.players||!game.players.length) return;
					var event=this;
					var start=false;
					var starts=[_status.currentPhase,event.source,event.player,game.me,game.players[0]];
					for(var i=0;i<starts.length;i++){
						if(get.itemtype(starts[i])=='player'){
							start=starts[i];break;
						}
					}
					if(!start) return;
					if(!game.players.contains(start)&&!game.dead.contains(start)){
						start=game.findNext(start);
					}
					var list=[];
					var list2=[];
					var mapx=[];
					var allbool=false;
					var roles=['player','source','target'];
					var listAdded;
					var mapxx;
					var addList=function(skill,player){
						if(listAdded[skill]) return;
						if(player.forbiddenSkills[skill]) return;
						if(player.disabledSkills[skill]) return;
						listAdded[skill]=true;
						var info=lib.skill[skill];
						var num=0;
						if(info.priority){
							num=info.priority*100;
						}
						if(info.silent){
							num++;
						}
						if(info.equipSkill) num-=30;
						if(info.ruleSkill) num-=30;
						if(info.firstDo){
							list.push([skill,player,num]);
							list.sort(function(a,b){
								return b[2]-a[2];
							});
							allbool=true;
							return;
						}
						else if(info.lastDo){
							list2.push([skill,player,num]);
							list2.sort(function(a,b){
								return b[2]-a[2];
							});
							allbool=true;
							return;
						}
						mapxx.list.push([skill,player,num]);
						mapxx.list.sort(function(a,b){
							return b[2]-a[2];
						});
						allbool=true;
					};
					var totalPopulation=game.players.length+game.dead.length+1;
					var player=start;
					var globalskill='global_'+name;
					var map=_status.connectMode?lib.playerOL:game.playerMap;
					for(var iwhile=0;iwhile<totalPopulation;iwhile++){
						var id=player.playerid;
						var mapxx={
							player:player,
							list:[],
							list2:[],
						};
						listAdded={};
						var notemp=player.skills.slice(0);
						for(var j in player.additionalSkills){
							if(!j.startsWith('hidden:')) notemp.addArray(player.additionalSkills[j]);
						}
						for(var j in player.tempSkills){
							if(notemp.contains(j)) continue;
							var expire=player.tempSkills[j];
							if(expire===name||
								(Array.isArray(expire)&&expire.contains(name))||
								(typeof expire==='function'&&expire(event,player,name))){
								delete player.tempSkills[j];
								player.removeSkill(j);
							}
							else if(get.objtype(expire)==='object'){
								for(var i=0;i<roles.length;i++){
									if(expire[roles[i]]&&player===event[roles[i]]&&
										(expire[roles[i]]===name||(Array.isArray(expire[roles[i]])&&expire[roles[i]].contains(name)))){
										delete player.tempSkills[j];
										player.removeSkill(j);
									}
								}
							}
						}
						if(lib.config.compatiblemode){
							(function(){
								var skills=player.getSkills('invisible').concat(lib.skill.global);
								game.expandSkills(skills);
								for(var i=0;i<skills.length;i++){
									var info=get.info(skills[i]);
									if(info&&info.trigger){
										var trigger=info.trigger;
										var add=false;
										if(trigger.player){
											if(typeof trigger.player==='string'){
												if(trigger.player===name) add=true;
											}
											else if(trigger.player.contains(name)) add=true;
										}
										if(trigger.target){
											if(typeof trigger.target==='string'){
												if(trigger.target===name) add=true;
											}
											else if(trigger.target.contains(name)) add=true;
										}
										if(trigger.source){
											if(typeof trigger.source==='string'){
												if(trigger.source===name) add=true;
											}
											else if(trigger.source.contains(name)) add=true;
										}
										if(trigger.global){
											if(typeof trigger.global==='string'){
												if(trigger.global===name) add=true;
											}
											else if(trigger.global.contains(name)) add=true;
										}
										if(add){
											addList(skills[i],player);
										}
									}
								}
							}());
						}
						else{
							for(var i=0;i<roles.length;i++){
								var triggername=player.playerid+'_'+roles[i]+'_'+name;
								if(lib.hook[triggername]){
									for(var j=0;j<lib.hook[triggername].length;j++){
										addList(lib.hook[triggername][j],player);
									}
								}
								triggername=roles[i]+'_'+name;
								if(lib.hook.globalskill[triggername]){
									for(var j=0;j<lib.hook.globalskill[triggername].length;j++){
										addList(lib.hook.globalskill[triggername][j],player);
									}
								}
							}
							if(lib.hook.globalskill[globalskill]){
								for(var j=0;j<lib.hook.globalskill[globalskill].length;j++){
									addList(lib.hook.globalskill[globalskill][j],player);
								}
							}
							for(var i in lib.hook.globaltrigger[name]){
								if(map[i]===player){
									for(var j=0;j<lib.hook.globaltrigger[name][i].length;j++){
										addList(lib.hook.globaltrigger[name][i][j],map[i]);
									}
								}
							}
						}
						mapx.push(mapxx);
						player=player.nextSeat;
						if(!player||player===start){
							break;
						}
					}
					
					if(allbool){
						var next=game.createEvent('arrangeTrigger',false,event);
						next.setContent('arrangeTrigger');
						next.list=list;
						next.list2=list2;
						next.map=mapx;
						next._trigger=event;
						next.triggername=name;
						//next.starter=start;
						event._triggering=next;
					}
				},
				untrigger:function(all,player){
					if(typeof all=='undefined') all=true;
					var evt=this._triggering;
					if(all){
						if(evt&&evt.map){
							for(var i=0;i<evt.map.length;i++){
								evt.map[i].list=[];
							}
							evt.list=[];
							if(evt.doing) evt.doing.list=[];
						};
						this._triggered=5;
					}
					else{
						if(player){
							this._notrigger.add(player);
							if(!evt||!evt.map) return;
							for(var i=0;i<evt.map.length;i++){
								if(evt.map[i].player==player) evt.map[i].list.length=0;
							}
						}
					}
				}
			},
			dialog:{
				add:function(item,noclick,zoom){
					if(typeof item=='string'){
						if(item.startsWith('###')){
							var items=item.slice(3).split('###');
							this.add(items[0],noclick,zoom);
							this.addText(items[1],items[1].length<=20,zoom);
						}
						else if(noclick){
							var strstr=item;
							item=ui.create.div('',this.content);
							item.innerHTML=strstr;
						}
						else{
							item=ui.create.caption(item,this.content);
						}
					}
					else if(get.objtype(item)=='div'){
						this.content.appendChild(item);
					}
					else if(get.itemtype(item)=='cards'){
						var buttons=ui.create.div('.buttons',this.content);
						if(zoom) buttons.classList.add('smallzoom');
						this.buttons=this.buttons.concat(ui.create.buttons(item,'card',buttons,noclick));
					}
					else if(get.itemtype(item)=='players'){
						var buttons=ui.create.div('.buttons',this.content);
						if(zoom) buttons.classList.add('smallzoom');
						this.buttons=this.buttons.concat(ui.create.buttons(item,'player',buttons,noclick));
					}
					else if(item[1]=='textbutton'){
						ui.create.textbuttons(item[0],this,noclick);
					}
					else{
						var buttons=ui.create.div('.buttons',this.content);
						if(zoom) buttons.classList.add('smallzoom');
						this.buttons=this.buttons.concat(ui.create.buttons(item[0],item[1],buttons,noclick));
					}
					if(this.buttons.length) {
						if(this.forcebutton!==false) this.forcebutton=true;
						if(this.buttons.length>3||(zoom&&this.buttons.length>5)){
							this.classList.remove('forcebutton-auto');
						}
						else if(!this.noforcebutton){
							this.classList.add('forcebutton-auto');
						}
					}
					ui.update();
					return item;
				},
				addText:function(str,center){
					if(str&&str.startsWith('<div')) this.add(str);
					else if(center!==false){
						this.add('<div class="text center">'+str+'</div>');
					}
					else{
						this.add('<div class="text">'+str+'</div>');
					}
					return this;
				},
				addSmall:function(item,noclick){
					return this.add(item,noclick,true);
				},
				addAuto:function(content){
					if(content&&content.length>4&&!this._hovercustomed){
						this.addSmall(content);
					}
					else{
						this.add(content);
					}
				},
				open:function(){
					if(this.noopen) return;
					for(var i=0;i<ui.dialogs.length;i++){
						if(ui.dialogs[i]==this){
							this.show();
							this.refocus();
							ui.dialogs.remove(this);
							ui.dialogs.unshift(this);
							ui.update();
							return this;
						}
						if(ui.dialogs[i].static) ui.dialogs[i].unfocus();
						else ui.dialogs[i].hide();
					}
					ui.dialog=this;
					var translate;
					if(lib.config.remember_dialog&&lib.config.dialog_transform&&!this.classList.contains('fixed')){
						translate=lib.config.dialog_transform;
						this._dragtransform=translate;
						this.style.transform='translate('+translate[0]+'px,'+translate[1]+'px) scale(0.8)';
					}
					else{
						this.style.transform='scale(0.8)';
					}
					this.style.transitionProperty='opacity,transform';
					this.style.opacity=0;
					ui.arena.appendChild(this);
					ui.dialogs.unshift(this);
					ui.update();
					ui.refresh(this);
					if(lib.config.remember_dialog&&lib.config.dialog_transform&&!this.classList.contains('fixed')){
						this.style.transform='translate('+translate[0]+'px,'+translate[1]+'px) scale(1)';
					}
					else{
						this.style.transform='scale(1)';
					}
					this.style.opacity=1;
					var that=this;
					setTimeout(function(){
						that.style.transitionProperty='';
					},500);
					return this;
				},
				close:function(){
					ui.dialogs.remove(this);
					this.delete();
					if(ui.dialogs.length>0){
						ui.dialog=ui.dialogs[0];
						ui.dialog.show();
						ui.dialog.refocus();
						ui.update();
					}
					// if(ui.arenalog){
					// 	ui.arenalog.classList.remove('withdialog');
					// }
					return this;
				},
				setCaption:function(str){
					this.querySelector('.caption').innerHTML=str;
					return this;
				}
			},
			control:{
				open:function(){
					ui.control.insertBefore(this,_status.createControl||ui.confirm);
					ui.controls.unshift(this);
					if(this.childNodes.length){
						this.style.transition='opacity 0.5s';
						ui.refresh(this);
						this.style.transform='translateX(-'+(this.offsetWidth/2)+'px)';
						this.style.opacity=1;
						ui.refresh(this);
						this.style.transition='';
					}
					else{
						this.animate('controlpressdownx',500);
					}
					ui.updatec();
					return this;
				},
				add:function(item){
					var node=document.createElement('div');
					this.appendChild(node);
					node.link=item;
					node.innerHTML=get.translation(item);
					node.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.control);
				},
				close:function(){
					this.animate('controlpressdownx',500);

					ui.controls.remove(this);
					this.delete();

					setTimeout(ui.updatec,100);


					if(ui.confirm==this) delete ui.confirm;
					if(ui.skills==this) delete ui.skills;
					if(ui.skills2==this) delete ui.skills2;
					if(ui.skills3==this) delete ui.skills3;
				},
				replace:function(){
					// this.animate('controlpressdownx',500);
					if(this.replaceTransition===false){
						this.style.transitionProperty='none';
						ui.refresh(this);
					}

					while(this.childNodes.length) this.firstChild.remove();
					var i,controls;
					if(Array.isArray(arguments[0])) controls=arguments[0];
					else controls=arguments;
					delete this.custom;
					for(i=0;i<controls.length;i++){
						if(typeof controls[i]=='function'){
							this.custom=controls[i];
						}
						else{
							this.add(controls[i]);
						}
					}
					if(this.childNodes.length){
						var width=0;
						for(i=0;i<this.childNodes.length;i++) width+=this.childNodes[i].offsetWidth;
						ui.refresh(this);
						this.style.width=width+'px';
					}
					ui.updatec();
					if(this.replaceTransition===false){
						var that=this;
						setTimeout(function(){
							that.style.transitionProperty='';
						},200);
					}
					return this;
				}
			},
			client:{
				send:function(){
					if(this.closed) return this;
					var args=Array.from(arguments);
					if(typeof args[0]=='function'){
						args.unshift('exec');
					}
					for(var i=1;i<args.length;i++){
						args[i]=get.stringifiedResult(args[i]);
					}
					try{
						this.ws.send(JSON.stringify(args));
					}
					catch(e){
						this.ws.close();
					}
					return this;
				},
				close:function(){
					lib.node.clients.remove(this);
					lib.node.observing.remove(this);
					if(ui.removeObserve&&!lib.node.observing.length){
						ui.removeObserve.remove();
						delete ui.removeObserve;
					}
					this.closed=true;
					if(_status.waitingForPlayer){
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].playerid==this.id){
								game.connectPlayers[i].uninitOL();
								delete game.connectPlayers[i].playerid;
							}
						}
						if(game.onlinezhu==this.id){
							game.onlinezhu=null;
						}
						game.updateWaiting();
					}
					else if(lib.playerOL[this.id]){
						var player=lib.playerOL[this.id];
						player.setNickname(player.nickname+' - 离线');
						game.broadcast(function(player){
							player.setNickname(player.nickname+' - 离线');
						},player);
						player.unwait('ai');
					}

					if(window.isNonameServer){
						document.querySelector('#server_count').innerHTML=lib.node.clients.length;
					}
					return this;
				}
			},
			nodews:{
				send:function(message){
					game.send('server','send',this.wsid,message);
				},
				on:function(type,func){
					this['on'+type]=func;
				},
				close:function(){
					game.send('server','close',this.wsid);
				}
			},
			ws:{
				onopen:function(){
					if(_status.connectCallback){
						_status.connectCallback(true);
						delete _status.connectCallback;
					}
				},
				onmessage:function(messageevent){
					if(messageevent.data=='heartbeat'){
						this.send('heartbeat');
						return;
					}
					var message;
					try{
						message=JSON.parse(messageevent.data);
						if(!Array.isArray(message)||
							typeof lib.message.client[message[0]]!=='function'){
							throw('err');
						}
						for(var i=1;i<message.length;i++){
							message[i]=get.parsedResult(message[i]);
						}
					}
					catch(e){
						console.log(e);
						console.log('invalid message: '+messageevent.data);
						return;
					}
					lib.message.client[message.shift()].apply(null,message);
				},
				onerror:function(e){
					if(this._nocallback) return;
					if(_status.connectCallback){
						_status.connectCallback(false);
						delete _status.connectCallback;
					}
					else{
						alert('连接失败');
					}
				},
				onclose:function(){
					if(this._nocallback) return;
					if(_status.connectCallback){
						_status.connectCallback(false);
						delete _status.connectCallback;
					}
					if(game.online||game.onlineroom){
						if((game.servermode||game.onlinehall)&&_status.over){

						}
						else{
							localStorage.setItem(lib.configprefix+'directstart',true);
							game.reload();
						}
					}
					else{
						// game.saveConfig('reconnect_info');
					}
					game.online=false;
					game.ws=null;
				}
			}
		},
		card:{
			list:[],
			cooperation_damage:{
				fullskin:true,
			},
			cooperation_draw:{
				fullskin:true,
				cardimage:'cooperation_damage',
			},
			cooperation_discard:{
				fullskin:true,
				cardimage:'cooperation_damage',
			},
			cooperation_use:{
				fullskin:true,
				cardimage:'cooperation_damage',
			},
			pss_paper:{
				type:'pss',
				fullskin:true,
			},
			pss_scissor:{
				type:'pss',
				fullskin:true,
			},
			pss_stone:{
				type:'pss',
				fullskin:true,
			},
			feichu_equip1:{
				type:"equip",
				subtype:"equip1",
			},
			feichu_equip2:{
				type:"equip",
				subtype:"equip2",
			},
			feichu_equip3:{
				type:"equip",
				subtype:"equip3",
			},
			feichu_equip4:{
				type:"equip",
				subtype:"equip4",
			},
			feichu_equip5:{
				type:"equip",
				subtype:"equip5",
			},
			zhengsu_leijin:{},
			zhengsu_mingzhi:{},
			zhengsu_bianzhen:{},
			disable_judge:{},
			group_wei:{fullskin:true},
			group_shu:{fullskin:true},
			group_wu:{fullskin:true},
			group_qun:{fullskin:true},
			group_key:{fullskin:true},
			group_jin:{fullskin:true},
			
			db_atk1:{
				type:'db_atk',
				fullimage:true,
			},
			db_atk2:{
				type:'db_atk',
				fullimage:true,
			},
			db_def1:{
				type:'db_def',
				fullimage:true,
			},
			db_def2:{
				type:'db_def',
				fullimage:true,
			},
		},
		filter:{
			all:()=>true,
			none:()=>false,
			//Check if the card does not count toward the player's hand limit
			//检测此牌是否不计入此角色的手牌上限
			ignoredHandcard:(card,player)=>game.checkMod(card,player,false,'ignoredHandcard',player),
			//Check if the card is giftable
			//检测此牌是否可赠予
			cardGiftable:(card,player,target,strict)=>{
				const mod=game.checkMod(card,player,target,'unchanged','cardGiftable',player);
				if(!mod||strict&&(mod=='unchanged'&&(get.position(card)!='h'||!get.cardtag(card,'gifts'))||player==target)) return false;
				return get.type(card,false)!='equip'||target.canEquip(card,true);
			},
			//Check if the card is recastable
			//检查此牌是否可重铸
			cardRecastable:(card,player,source,strict)=>{
				if(typeof player=='undefined') player=get.owner(card);
				const mod=game.checkMod(card,player,source,'unchanged','cardRecastable',player);
				if(!mod) return false;
				if(strict&&mod=='unchanged'){
					if(get.position(card)!='h') return false;
					const info=get.info(card),recastable=info.recastable||info.chongzhu;
					return Boolean(typeof recastable=='function'?recastable(_status.event,player):recastable);
				}
				return true;
			},
			//装备栏相关
			canBeReplaced:function(card,player){
				var mod=game.checkMod(card,player,'unchanged','canBeReplaced',player);
				if(mod!='unchanged') return mod;
				return true;
			},
			//装备栏 END
			buttonIncluded:function(button){
				return !(_status.event.excludeButton&&_status.event.excludeButton.contains(button));
			},
			filterButton:function(button){
				return true;
			},
			cardSavable:function(card,player,target){
				if(get.itemtype(card)=='card'){
					var mod2=game.checkMod(card,player,'unchanged','cardEnabled2',player);
					if(mod2!='unchanged') return mod2;
				}
				var mod=game.checkMod(card,player,target,'unchanged','cardSavable',player);
				if(mod!='unchanged') return mod;
				var savable=get.info(card).savable;
				if(typeof savable=='function') savable=savable(card,player,target);
				return savable;
			},
			filterTrigger:function(event,player,name,skill){
				if(player._hookTrigger){
					for(var i=0;i<player._hookTrigger.length;i++){
						var info=lib.skill[player._hookTrigger[i]].hookTrigger;
						if(info){
							if(info.block&&info.block(event,player,name,skill)){
								return false;
							}
						}
					}
				}
				var fullskills=game.expandSkills(player.getSkills(false).concat(lib.skill.global));
				var info=get.info(skill);
				if(((info&&info.noHidden)||get.mode()!='guozhan')&&!fullskills.contains(skill)){
					return false;
				}
				if(!info.trigger) return false;
				var bool=false;
				var has=function(obj){
					if(typeof obj=='string') return obj==name;
					else if(obj.contains(name)) return true;
					return false;
				}
				for(var i in info.trigger){
					if((i=='global'||player==event[i])&&has(info.trigger[i])){
						bool=true;break;
					}
				}
				if(!bool) return false;
				if(info.filter&&!info.filter(event,player,name)){
					return false;
				}
				if(event._notrigger.contains(player)&&!lib.skill.global.contains(skill)){
					return false;
				}
				if(typeof info.usable=='number'&&player.hasSkill('counttrigger')&&
					player.storage.counttrigger&&player.storage.counttrigger[skill]>=info.usable){
					return false;
				}
				if(info.round&&(info.round-(game.roundNumber-player.storage[skill+'_roundcount'])>0)){
					return false;
				}
				return true;
			},
			characterDisabled:function(i,libCharacter){
				if(!lib.character[i]||lib.character[i][4]&&lib.character[i][4].contains('forbidai')) return true;
				if(lib.character[i][4]&&lib.character[i][4].contains('unseen')) return true;
				if(lib.config.forbidai.contains(i)) return true;
				if(lib.characterFilter[i]&&!lib.characterFilter[i](get.mode())) return true;
				if(_status.connectMode){
					if(lib.configOL.banned.contains(i)||lib.connectBanned.contains(i)) return true;
					var double_character=false;
					if(lib.configOL.mode=='guozhan'){
						double_character=true;
					}
					else if(lib.configOL.double_character&&(lib.configOL.mode=='identity'||lib.configOL.mode=='stone')){
						double_character=true;
					}
					else if(lib.configOL.double_character_jiange&&(lib.configOL.mode=='versus'&&_status.mode=='jiange')){
						double_character=true;
					}
					if(double_character&&lib.config.forbiddouble.contains(i)){
						return true;
					}
					// if(lib.configOL.ban_weak){
					// 	if(lib.config.replacecharacter[i]&&libCharacter&&libCharacter[lib.config.replacecharacter[i]]) return true;
					// 	if(lib.config.forbidall.contains(i)) return true;
					// 	if(!double_character&&get.rank(i,true)<=2){
					// 		return true;
					// 	}
					// }
					// if(lib.configOL.ban_strong&&get.rank(i,true)>=8){
					// 	return true;
					// }
				}
				else{
					if(lib.config.banned.contains(i)) return true;
					var double_character=false;
					if(get.mode()=='guozhan'){
						double_character=true;
					}
					else if(get.config('double_character')&&(lib.config.mode=='identity'||lib.config.mode=='stone')){
						double_character=true;
					}
					else if(get.config('double_character_jiange')&&(lib.config.mode=='versus'&&_status.mode=='jiange')){
						double_character=true;
					}
					if(double_character&&lib.config.forbiddouble.contains(i)){
						return true;
					}
					// if(get.config('ban_weak')){
					// 	if(lib.config.replacecharacter[i]&&lib.character[lib.config.replacecharacter[i]]) return true;
					// 	if(lib.config.forbidall.contains(i)) return true;
					// 	if(!double_character&&get.rank(i,true)<=2){
					// 		return true;
					// 	}
					// }
					// if(get.config('ban_strong')&&get.rank(i,true)>=8){
					// 	return true;
					// }
				}
			},
			characterDisabled2:function(i){
				var info=lib.character[i];
				if(!info) return true;
				if(info[4]){
					if(info[4].contains('boss')) return true;
					if(info[4].contains('hiddenboss')) return true;
					if(info[4].contains('minskin')) return true;
					if(info[4].contains('unseen')) return true;
					if(info[4].contains('forbidai')&&(!_status.event.isMine||!_status.event.isMine())) return true;
					if(lib.characterFilter[i]&&!lib.characterFilter[i](get.mode())) return true;
				}
				return false;
			},
			skillDisabled:function(skill){
				if(!lib.translate[skill]||!lib.translate[skill+'_info']) return true;
				var info=lib.skill[skill];
				if(info&&!info.unique&&!info.temp&&!info.sub&&!info.fixed&&!info.vanish){
					return false;
				}
				return true;
			},
			cardEnabled:function(card,player,event){
				if(player==undefined) player=_status.event.player;
				if(!player) return false;
				if(get.itemtype(card)=='card'){
					var mod2=game.checkMod(card,player,event,'unchanged','cardEnabled2',player);
					if(mod2!='unchanged') return mod2;
				}
				card=get.autoViewAs(card);
				if(event==='forceEnable'){
					var mod=game.checkMod(card,player,event,'unchanged','cardEnabled',player);
					if(mod!='unchanged') return mod;
					return true;
				}
				else{
					var filter=get.info(card).enable;
					if(!filter) return;
					var mod=game.checkMod(card,player,event,'unchanged','cardEnabled',player);
					if(mod!='unchanged') return mod;
					if(typeof filter=='boolean') return filter;
					if(typeof filter=='function') return filter(card,player,event);
				}
			},
			cardRespondable:function(card,player,event){
				event=event||_status.event;
				if(event.name!='chooseToRespond') return true;
				var source=event.getParent().player;
				if(source&&source!=player){
					if(source.hasSkillTag('norespond',false,[card,player,event],true)){
						return false;
					}
				}
				if(player==undefined) player=_status.event.player;
				if(get.itemtype(card)=='card'){
					var mod2=game.checkMod(card,player,event,'unchanged','cardEnabled2',player);
					if(mod2!='unchanged') return mod2;
				}
				var mod=game.checkMod(card,player,'unchanged','cardRespondable',player);
				if(mod!='unchanged') return mod;
				return true;
			},
			cardUsable2:function(card,player,event){
				card=get.autoViewAs(card);
				var info=get.info(card);
				if(info.updateUsable=='phaseUse'){
					event=event||_status.event;
					if(event.type=='chooseToUse_button') event=event.getParent();
					if(player!=_status.event.player) return true;
					if(event.getParent().name!='phaseUse') return true;
					if(event.getParent().player!=player) return true;
				}
				var num=info.usable;
				if(typeof num=='function') num=num(card,player);
				num=game.checkMod(card,player,num,'cardUsable',player);
				if(typeof num!='number') return true;
				else return(player.countUsed(card)<num);
			},
			cardUsable:function(card,player,event){
				card=get.autoViewAs(card);
				var info=get.info(card);
				event=event||_status.event;
				if(event.type=='chooseToUse_button') event=event.getParent();
				if(player!=_status.event.player) return true;
				if(info.updateUsable=='phaseUse'){
					if(event.getParent().name!='phaseUse') return true;
					if(event.getParent().player!=player) return true;
				}
				event.addCount_extra=true;
				var num=info.usable;
				if(typeof num=='function') num=num(card,player);
				num=game.checkMod(card,player,num,'cardUsable',player);
				if(typeof num!='number'){
					return (typeof num=='boolean')?num:true;
				}
				if(player.countUsed(card)<num) return true;
				if(game.hasPlayer(function(current){
					return game.checkMod(card,player,current,false,'cardUsableTarget',player);
				})){
					return true;
				}
				return false;
			},
			cardDiscardable:function(card,player,event){
				event=event||_status.event;
				if(typeof event!='string') event=event.getParent().name;
				var mod=game.checkMod(card,player,event,'unchanged','cardDiscardable',player);
				if(mod!='unchanged') return mod;
				return true;
			},
			canBeDiscarded:function(card,player,target,event){
				event=event||_status.event;
				if(typeof event!='string') event=event.getParent().name;
				var mod=game.checkMod(card,player,target,event,'unchanged','canBeDiscarded',target);
				if(mod!='unchanged') return mod;
				return true;
			},
			canBeGained:function(card,player,target,event){
				event=event||_status.event;
				if(typeof event!='string') event=event.getParent().name;
				var mod=game.checkMod(card,player,target,event,'unchanged','canBeGained',target);
				if(mod!='unchanged') return mod;
				return true;
			},
			cardAiIncluded:function(card){
				if(_status.event.isMine()) return true;
				return (_status.event._aiexclude.contains(card)==false);
			},
			filterCard:function(card,player,event){
				var info=get.info(card);
				//if(info.toself&&!lib.filter.targetEnabled(card,player,player)) return false;
				if(player==undefined) player=_status.event.player;
				if(!lib.filter.cardEnabled(card,player,event)||!lib.filter.cardUsable(card,player,event)) return false;
				if(info.notarget) return true;
				var range;
				var select=get.copy(info.selectTarget);
				if(select==undefined){
					if(info.filterTarget==undefined) return true;
					range=[1,1];
				}
				else if(typeof select=='number') range=[select,select];
				else if(get.itemtype(select)=='select') range=select;
				else if(typeof select=='function') range=select(card,player);
				game.checkMod(card,player,range,'selectTarget',player);
				if(!range||range[1]!=-1) return true;
				var filterTarget=(event&&event.filterTarget)?event.filterTarget:lib.filter.filterTarget;
				return game.hasPlayer(function(current){
					return filterTarget(card,player,current);
				});
			},
			targetEnabledx:function(card,player,target){
				if(!card) return false;
				var event=_status.event;
				if(event._backup&&event._backup.filterCard==lib.filter.filterCard&&(!lib.filter.cardEnabled(card,player,event)||!lib.filter.cardUsable(card,player,event))) return false;
				if(event.addCount_extra){
					if(!lib.filter.cardUsable2(card,player)&&!game.checkMod(card,player,target,false,'cardUsableTarget',player)) return false;
				}
				var info=get.info(card);
				if(info.singleCard&&info.filterAddedTarget&&ui.selected.targets.length) return Boolean(info.filterAddedTarget(card,player,target,ui.selected.targets[ui.selected.targets.length-1]));
				return lib.filter.targetEnabled.apply(this,arguments);
			},
			targetEnabled:function(card,player,target){
				if(!card) return false;
				var info=get.info(card);
				var filter=info.filterTarget;
				if(!info.singleCard||ui.selected.targets.length==0){
					var mod=game.checkMod(card,player,target,'unchanged','playerEnabled',player);
					if(mod!='unchanged') return mod;
					var mod=game.checkMod(card,player,target,'unchanged','targetEnabled',target);
					if(mod!='unchanged') return mod;
				}
				if(typeof filter=='boolean') return filter;
				if(typeof filter=='function') return Boolean(filter(card,player,target));
			},
			targetEnabled2:function(card,player,target){
				if(lib.filter.targetEnabled(card,player,target)) return true;
				if(!card) return false;

				if(game.checkMod(card,player,target,'unchanged','playerEnabled',player)==false) return false;
				if(game.checkMod(card,player,target,'unchanged','targetEnabled',target)==false) return false;

				var filter=get.info(card).modTarget;
				if(typeof filter=='boolean') return filter;
				if(typeof filter=='function') return Boolean(filter(card,player,target));
				return false;
			},
			targetEnabled3:function(card,player,target){
				if(!card) return false;
				var info=get.info(card);

				if(info.filterTarget==true) return true;
				if(typeof info.filterTarget=='function'&&info.filterTarget(card,player,target)) return true;

				if(info.modTarget==true) return true;
				if(typeof info.modTarget=='function'&&info.modTarget(card,player,target)) return true;
				return false;
			},
			targetInRange:function(card,player,target){
				var info=get.info(card);
				var range=info.range;
				var outrange=info.outrange;
				if(range==undefined&&outrange==undefined) return true;
				
				var mod=game.checkMod(card,player,target,'unchanged','targetInRange',player);
				var extra=0;
				if(mod!='unchanged'){
					if(typeof mod=='boolean') return mod;
					if(typeof mod=='number') extra=mod;
				}
				if(typeof info.range=='function') return info.range(card,player,target);
				
				if(player.hasSkill('undist')||target.hasSkill('undist')) return false;
				for(var i in range){
					if(i=='attack'){
						var range2=player.getAttackRange();
						if(range2<=0) return false;
						var distance=get.distance(player,target)+extra;
						if(range[i]<=distance-range2) return false;
					}
					else{
						var distance=get.distance(player,target,i)+extra;
						if(range[i]<distance) return false;
					}
				}
				for(var i in outrange){
					if(i=='attack'){
						var range2=player.getAttackRange();
						if(range2<=0) return false;
						var distance=get.distance(player,target)+extra;
						if(outrange[i]>distance-range2+1) return false;
					}
					else{
						var distance=get.distance(player,target,i)+extra;
						if(outrange[i]>distance) return false;
					}
				}
				return true;
			},
			filterTarget:function(card,player,target){
				return (lib.filter.targetEnabledx(card,player,target)&&
					lib.filter.targetInRange(card,player,target));
			},
			filterTarget2:function(card,player,target){
				return (lib.filter.targetEnabled2(card,player,target)&&
					lib.filter.targetInRange(card,player,target));
			},
			notMe:function(card,player,target){
				return player!=target;
			},
			isMe:function(card,player,target){
				return player==target;
			},
			attackFrom:function(card,player,target){
				return get.distance(player,target,'attack')<=1;
			},
			globalFrom:function(card,player,target){
				return get.distance(player,target)<=1;
			},
			selectCard:function(){
				return [1,1];
			},
			selectTarget:function(card,player){
				if(!card) card=get.card();
				if(!player) player=get.player();
				if(card==undefined) return;
				var range,info=get.info(card);
				var select=get.copy(info.selectTarget);
				if(select==undefined){
					if(info.filterTarget==undefined) return [0,0];
					range=[1,1];
				}
				else if(typeof select=='number') range=[select,select];
				else if(get.itemtype(select)=='select') range=select;
				else if(typeof select=='function') range=select(card,player);
				game.checkMod(card,player,range,'selectTarget',player);
				if(info.singleCard&&info.filterAddedTarget) return [range[0]*2,range[1]*2];
				return range;
			},
			judge:function(card,player,target){
				return target.canAddJudge(card);
			},
			autoRespondSha:function(){
				return !this.player.hasSha(true);
			},
			autoRespondShan:function(){
				return !this.player.hasShan();
			},
			wuxieSwap:function(event){
				if(event.type=='wuxie'){
					if(ui.wuxie&&ui.wuxie.classList.contains('glow')){
						return true;
					}
					if(ui.tempnowuxie&&ui.tempnowuxie.classList.contains('glow')&&event.state>0){
						var triggerevent=event.getTrigger();
						if(triggerevent){
							if(ui.tempnowuxie._origin==triggerevent.parent.id){
								return true;
							}
						}
						else if(ui.tempnowuxie._origin==_status.event.id2){
							return true;
						}
					}
					if(lib.config.wuxie_self){
						var tw=event.info_map;
						if(tw.player&&tw.player.isUnderControl(true)&&!tw.player.hasSkillTag('noautowuxie')&&
							(!tw.targets||tw.targets.length<=1)&&!tw.noai){
							return true;
						}
					}
				}
			}
		},
		sort:{
			nature:function(a,b){
				return (lib.nature.get(b)||0)-(lib.nature.get(a)||0);
			},
			group:function(a,b){
				const groupSort=function(group){
					let base=0;
					if(group=='wei') return base;
					if(group=='shu') return base+1;
					if(group=='wu') return base+2;
					if(group=='qun') return base+3;
					if(group=='jin') return base+4;
					if(group=='key') return base+5;
					if(group=='western') return base+6;
					if(group=='shen') return base+7;
					if(group=='double') return base+7;
					return base+9;
				}
				return groupSort(a)-groupSort(b);
			},
			character:function(a,b){
				const groupSort=function(name){
					const info=get.character(name);
					if(!info) return 7;
					let base=0;
					if(get.is.double(name,true)) base=9;
					const group=info[1];
					if(group=='shen') return base-1;
					if(group=='wei') return base;
					if(group=='shu') return base+1;
					if(group=='wu') return base+2;
					if(group=='qun') return base+3;
					if(group=='jin') return base+4;
					if(group=='key') return base+5;
					if(group=='western') return base+6;
					return base+7;
				}
				const del=groupSort(a)-groupSort(b);
				if(del!=0) return del;
				let aa=a,bb=b;
				if(a.includes('_')){
					a=a.slice(a.indexOf('_')+1);
				}
				if(b.includes('_')){
					b=b.slice(b.indexOf('_')+1);
				}
				if(a!=b){
					return a>b?1:-1;
				}
				return aa>bb?1:-1;
			},
			card:function(a,b){
				var typeSort=function(name){
					var type=get.type(name);
					if(!type) return 10;
					if(type=='basic') return -1;
					if(type=='trick') return 0;
					if(type=='delay') return 1;
					if(type=='equip'){
						var type2=get.subtype(name);
						if(type2&&type2.slice) return 1+parseInt(type2.slice(5)||7);
						return 8.5
					}
					return 9;
				}
				var del=typeSort(a)-typeSort(b);
				if(del!=0) return del;
				var aa=a,bb=b;
				if(a.includes('_')){
					a=a.slice(a.indexOf('_')+1);
				}
				if(b.includes('_')){
					b=b.slice(b.indexOf('_')+1);
				}
				if(a!=b){
					return a>b?1:-1;
				}
				return aa>bb?1:-1;
			},
			random:function(){
				return (Math.random()-0.5);
			},
			seat:function(a,b){
				var player=lib.tempSortSeat||_status.event.player;
				var delta=get.distance(player,a,'absolute')-get.distance(player,b,'absolute');
				if(delta) return delta;
				delta=parseInt(a.dataset.position)-parseInt(b.dataset.position);
				if(player.side==game.me.side) return delta;
				return -delta;
			},
			position:function(a,b){
				return parseInt(a.dataset.position)-parseInt(b.dataset.position);
			},
			priority:function(a,b){
				var i1=get.info(a[0]),i2=get.info(b[0]);
				if(i1.priority==undefined) i1.priority=0;
				if(i2.priority==undefined) i2.priority=0;
				if(i1.priority==i2.priority){
					if(i1.forced==undefined&&i2.forced==undefined) return 0;
					if(i1.forced&&i2.forced) return 0;
					if(i1.forced) return 1;
					if(i2.forced) return -1;
				}
				return i2.priority-i1.priority;
			},
			number:function(a,b){
				return get.number(a)-get.number(b);
			},
			number2:function(a,b){
				return get.number(b)-get.number(a);
			},
			capt:function(a,b){
				var aa=a,bb=b;
				if(aa.includes('_')){
					aa=aa.slice(aa.indexOf('_')+1);
				}
				if(bb.includes('_')){
					bb=bb.slice(bb.indexOf('_')+1);
				}
				if(aa!=bb){
					return aa>bb?1:-1;
				}
				return a>b?1:-1;
			},
			name:function(a,b){
				if(a>b) return 1;
				if(a<b) return -1;
				return 0;
			}
		},
		skill:{
			expandedSlots:{
				markimage:'image/card/expandedSlots.png',
				intro:{
					markcount:function(storage,player){
						var all=0,storage=player.expandedSlots;
						if(!storage) return 0;
						for(var key in storage){
							var num=storage[key];
							if(typeof num=='number'&&num>0){
								all+=num;
							}
						}
						return all;
					},
					content:function(storage,player){
						storage=player.expandedSlots;
						if(!storage) return '当前没有扩展装备栏';
						var keys=Object.keys(storage).sort();
						var str='';
						for(var key of keys){
							var num=storage[key];
							if(typeof num=='number'&&num>0){
								str+='<li>'+get.translation(key)+'栏:'+num+'个<br>'
							}
						}
						if(str.length) return str.slice(0,str.length-4);
						return '当前没有扩展装备栏';
					},
				},
			},
			charge:{
				markimage:'image/card/charge.png',
				intro:{
					content:'当前蓄力点数:#',
				},
			},
			cooperation:{
				charlotte:true,
				trigger:{
					global:['phaseAfter','dieAfter'],
				},
				forced:true,
				lastDo:true,
				filter:function(event,player){
					if(event.name=='die'&&event.player.isAlive()) return false;
					var storage=player.getStorage('cooperation');
					for(var info of storage){
						if(info.target==event.player) return true;
					}
					return false;
				},
				content:function(){
					for(var i=0;i<player.storage.cooperation.length;i++){
						var info=player.storage.cooperation[i];
						if(info.target==trigger.player){
							player.removeCooperation(info);
							i--;
						}
					}
				},
				onremove:function(player,skill){
					var storage=player.getStorage(skill);
					var reasons=[];
					for(var i of storage) reasons.add(i.type);
					for(var i of reasons) player.removeSkill(skill+'_'+i);
					delete player.storage[i];
				},
				subSkill:{
					damage:{
						mark:true,
						trigger:{global:'damage'},
						forced:true,
						charlotte:true,
						popup:false,
						firstDo:true,
						filter:function(event,player){
							if(!event.source) return false;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='damage'&&(event.source==player||event.source==info.target)) return true;
							}
							return false;
						},
						checkx:(info)=>(info.damage&&info.damage>3),
						content:function(){
							var source=trigger.source;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='damage'&&(source==player||source==info.target)){
									if(!info.damage) info.damage=0;
									info.damage+=trigger.num;
								}
							}
							player.markSkill('cooperation_damage');
						},
						marktext:'仇',
						intro:{
							name:'协力 - 同仇',
							markcount:function(storage,player){
								return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){
									return info.damage||0;
								}));
							},
							content:function(storage,player){
								var str='',storage=player.getStorage('cooperation');
								for(var info of storage){
									if(info.type=='damage'){
										str+='<br><li>协力角色:'+get.translation(info.target);
										str+='<br><li>协力原因:'+get.translation(info.reason);
										str+='<br><li>协力进度:'
										var num=(info.damage||0);
										str+=num;
										str+='/4';
										str+=(num>3?' (已完成)':' (未完成)');
										str+='<br>  ';
									}
								}
								return str.slice(4,str.length-6);
							},
						},
					},
					draw:{
						mark:true,
						trigger:{global:'gainAfter'},
						forced:true,
						charlotte:true,
						popup:false,
						firstDo:true,
						filter:function(event,player){
							if(event.getParent().name!='draw') return false;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='draw'&&(event.player==player||event.player==info.target)) return true;
							}
							return false;
						},
						checkx:(info)=>(info.draw&&info.draw>7),
						content:function(){
							var source=trigger.player;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='draw'&&(source==player||source==info.target)){
									if(!info.draw) info.draw=0;
									info.draw+=trigger.cards.length;
								}
							}
							player.markSkill('cooperation_draw');
						},
						marktext:'进',
						intro:{
							name:'协力 - 并进',
							markcount:function(storage,player){
								return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){
									return info.draw||0;
								}));
							},
							content:function(storage,player){
								var str='',storage=player.getStorage('cooperation');
								for(var info of storage){
									if(info.type=='draw'){
										str+='<br><li>协力角色:'+get.translation(info.target);
										str+='<br><li>协力原因:'+get.translation(info.reason);
										str+='<br><li>协力进度:'
										var num=(info.draw||0);
										str+=num;
										str+='/8';
										str+=(num>7?' (已完成)':' (未完成)');
										str+='<br>  ';
									}
								}
								return str.slice(4,str.length-6);
							},
						},
					},
					discard:{
						mark:true,
						trigger:{global:'loseAfter'},
						forced:true,
						charlotte:true,
						popup:false,
						firstDo:true,
						filter:function(event,player){
							if(event.type!='discard') return false;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='discard'&&(event.player==player||event.player==info.target)) return true;
							}
							return false;
						},
						checkx:(info)=>(info.discard&&info.discard.length>3),
						content:function(){
							var source=trigger.player;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='discard'&&(source==player||source==info.target)){
									if(!info.discard) info.discard=[];
									for(var i of trigger.cards2){
										var suit=get.suit(i,player);
										if(lib.suit.contains(suit)) info.discard.add(suit);
									}
								}
							}
							player.markSkill('cooperation_discard');
						},
						marktext:'财',
						intro:{
							name:'协力 - 疏财',
							markcount:function(storage,player){
								return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){
									return info.discard?info.discard.length:0;
								}));
							},
							content:function(storage,player){
								var str='',storage=player.getStorage('cooperation');
								for(var info of storage){
									if(info.type=='discard'){
										str+='<br><li>协力角色:'+get.translation(info.target);
										str+='<br><li>协力原因:'+get.translation(info.reason);
										str+='<br><li>进度:';
										var suits=info.discard||[];
										var suits2=[['spade','♠','♤'],['heart','♥','♡'],['club','♣','♧'],['diamond','♦','♢']];
										for(var i of suits2){
											str+=(suits.contains(i[0])?i[1]:i[2]);
										}
										str+=(suits.length>3?' (已完成)':' (未完成)');
										str+='<br>  ';
									}
								}
								return str.slice(4,str.length-6);
							},
						},
					},
					use:{
						mark:true,
						trigger:{global:'useCard1'},
						forced:true,
						charlotte:true,
						popup:false,
						firstDo:true,
						filter:function(event,player){
							var suit=get.suit(event.card);
							if(!lib.suit.contains(suit)) return false;
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='use'
									&&(event.player==player||event.player==info.target)&&
									(!info.used||!info.used.contains(suit))) return true;
							}
							return false;
						},
						checkx:(info)=>(info.used&&info.used.length>3),
						content:function(){
							var source=trigger.player,suit=get.suit(trigger.card);
							var storage=player.getStorage('cooperation');
							for(var info of storage){
								if(info.type=='use'&&(source==player||source==info.target)){
									if(!info.used) info.used=[];
									info.used.add(suit);
								}
							}
							player.markSkill('cooperation_use');
						},
						marktext:'戮',
						intro:{
							name:'协力 - 戮力',
							markcount:function(storage,player){
								return Math.max.apply(Math,player.getStorage('cooperation').map(function(info){
									return info.used?info.used.length:0;
								}));
							},
							content:function(storage,player){
								var str='',storage=player.getStorage('cooperation');
								for(var info of storage){
									if(info.type=='use'){
										str+='<br><li>协力角色:'+get.translation(info.target);
										str+='<br><li>协力原因:'+get.translation(info.reason);
										str+='<br><li>进度:';
										var suits=info.used||[];
										var suits2=[['spade','♠','♤'],['heart','♥','♡'],['club','♣','♧'],['diamond','♦','♢']];
										for(var i of suits2){
											str+=(suits.contains(i[0])?i[1]:i[2]);
										}
										str+=(suits.length>3?' (已完成)':' (未完成)');
										str+='<br>  ';
									}
								}
								return str.slice(4,str.length-6);
							},
						},
					},
				},
			},
			zhengsu:{
				trigger:{player:'phaseDiscardEnd'},
				forced:true,
				charlotte:true,
				filter:function(event,player){
					return (player.storage.zhengsu_leijin||player.storage.zhengsu_bianzhen||player.storage.zhengsu_mingzhi);
				},
				content:function(){
					player.chooseDrawRecover(2,'整肃奖励:摸两张牌或回复1点体力');
				},
				subSkill:{
					leijin:{
						mod:{
							aiOrder:function(player,card,num){
								if(typeof card.number!='number') return;
								var history=player.getHistory('useCard',evt=>evt.isPhaseUsing());
								if(history.length==0) return num+10*(14-card.number);
								var num=get.number(history[0].card);
								if(!num) return;
								for(var i=1;i<history.length;i++){
									var num2=get.number(history[i].card);
									if(!num2||num2<=num) return;
									num=num2;
								}
								if(card.number>num) return num+10*(14-card.number);
							},
						},
						mark:true,
						trigger:{player:'useCard1'},
						lastDo:true,
						charlotte:true,
						forced:true,
						popup:false,
						onremove:true,
						filter:function(event,player){
							return player.isPhaseUsing()&&player.storage.zhengsu_leijin!==false;
						},
						content:function(){
							var list=player.getHistory('useCard',function(evt){
								return evt.isPhaseUsing(player);
							});
							var goon=true;
							for(var i=0;i<list.length;i++){
								var num=get.number(list[i].card);
								if(typeof num!='number'){
									goon=false;
									break;
								}
								if(i>0){
									var num2=get.number(list[i-1].card);
									if(typeof num2!='number'||num2>=num){
										goon=false;
										break;
									}
								}
							}
							if(!goon){
								game.broadcastAll(function(player){
									player.storage.zhengsu_leijin=false;
									if(player.marks.zhengsu_leijin) player.marks.zhengsu_leijin.firstChild.innerHTML='╳';
									delete player.storage.zhengsu_leijin_markcount;
								},player);
							}
							else{
								if(list.length>2){
									game.broadcastAll(function(player,num){
										if(player.marks.zhengsu_leijin) player.marks.zhengsu_leijin.firstChild.innerHTML='○';
										player.storage.zhengsu_leijin=true;
										player.storage.zhengsu_leijin_markcount=num;
									},player,num);
								}
								else game.broadcastAll(function(player,num){
									player.storage.zhengsu_leijin_markcount=num;
								},player,num);
							}
							player.markSkill('zhengsu_leijin');
						},
						intro:{
							content:'<li>条件:回合内所有于出牌阶段使用的牌点数递增且不少于三张。',
						},
					},
					bianzhen:{
						mark:true,
						trigger:{player:'useCard1'},
						firstDo:true,
						charlotte:true,
						forced:true,
						popup:false,
						onremove:true,
						filter:function(event,player){
							return player.isPhaseUsing()&&player.storage.zhengsu_bianzhen!==false;
						},
						content:function(){
							var list=player.getHistory('useCard',function(evt){
								return evt.isPhaseUsing();
							});
							var goon=true,suit=get.suit(list[0].card,false);
							if(suit=='none'){
								goon=false;
							}
							else{
								for(var i=1;i<list.length;i++){
									if(get.suit(list[i])!=suit){
										goon=false;
										break;
									}
								}
							}
							if(!goon){
								game.broadcastAll(function(player){
									player.storage.zhengsu_bianzhen=false;
									if(player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML='╳';
								},player);
							}
							else{
								if(list.length>1){
									game.broadcastAll(function(player){
										if(player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML='○';
										player.storage.zhengsu_bianzhen=true;
									},player);
								}
								else game.broadcastAll(function(player,suit){
									if(player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML=get.translation(suit);
								},player,suit);
							}
							player.markSkill('zhengsu_bianzhen');
						},
						intro:{
							content:'<li>条件:回合内所有于出牌阶段使用的牌花色相同且不少于两张。',
						},
						ai:{
							effect:{
								player_use:function(card,player,target){
									if(typeof card!='object'||!player.isPhaseUsing()) return;
									var suitx=get.suit(card);
									var history=player.getHistory('useCard');
									if(!history.length){
										var val=0;
										if(player.hasCard(function(cardx){
											return get.suit(cardx)==suitx&&card!=cardx&&(!card.cards||!card.cards.contains(cardx))&&player.hasValueTarget(cardx);
										},'hs')) val=[2,0.1];
										if(val) return val;
										return;
									}
									var num=0;
									var suit=false;
									for(var i=0;i<history.length;i++){
										var suit2=get.suit(history[i].card);
										if(!lib.suit.contains(suit2)) return;
										if(suit&&suit!=suit2) return;
										suit=suit2;
										num++;
									}
									if(suitx==suit&&num==1) return [1,0.1];
									if(suitx!=suit&&(num>1||num<=1&&player.hasCard(function(cardx){
										return get.suit(cardx)==suit&&player.hasValueTarget(cardx);
									},'hs'))) return 'zeroplayertarget';
								},
							},
						},
					},
					mingzhi:{
						mark:true,
						trigger:{player:'loseAfter'},
						firstDo:true,
						charlotte:true,
						forced:true,
						popup:false,
						onremove:true,
						filter:function(event,player){
							if(player.storage.zhengsu_mingzhi===false||event.type!='discard') return false;
							var evt=event.getParent('phaseDiscard');
							return evt&&evt.player==player;
						},
						content:function(){
							var goon=true,list=[];
							player.getHistory('lose',function(event){
								if(!goon||event.type!='discard') return false;
								var evt=event.getParent('phaseDiscard');
								if(evt&&evt.player==player){
									for(var i of event.cards2){
										var suit=get.suit(i,player);
										if(list.contains(suit)){
											goon=false;
											break;
										}
										else list.push(suit);
									}
								}
							});
							if(!goon){
								game.broadcastAll(function(player){
									player.storage.zhengsu_mingzhi=false;
									if(player.marks.zhengsu_mingzhi) player.marks.zhengsu_mingzhi.firstChild.innerHTML='╳';
									delete player.storage.zhengsu_mingzhi_list;
								},player);
							}
							else{
								if(list.length>1){
									game.broadcastAll(function(player,list){
										if(player.marks.zhengsu_mingzhi) player.marks.zhengsu_mingzhi.firstChild.innerHTML='○';
										player.storage.zhengsu_mingzhi=true;
										player.storage.zhengsu_mingzhi_list=list;
										player.storage.zhengsu_mingzhi_markcount=list.length;
									},player,list);
								}
								else game.broadcastAll(function(player,list){
									player.storage.zhengsu_mingzhi_list=list;
									player.storage.zhengsu_mingzhi_markcount=list.length;
								},player,list);
							}
							player.markSkill('zhengsu_mingzhi');
						},
						intro:{
							content:'<li>条件:回合内所有于弃牌阶段弃置的牌花色均不相同且不少于两张。',
						},
					},
				},
			},
			renku:{
				intro:{
					markcount:function(){
						return _status.renku.length;
					},
					mark:function(dialog,content,player){
						if(!_status.renku.length) return '仁库中没有牌';
						else dialog.addAuto(_status.renku);
					},
					content:function(){
						if(!_status.renku.length) return '仁库中没有牌';
						return get.translation(_status.renku);
					},
				},
			},
			_showHiddenCharacter:{
				trigger:{player:['changeHp','phaseBeginStart','loseMaxHpBegin','gainMaxHpBegin']},
				firstDo:true,
				forced:true,
				popup:false,
				priority:25,
				filter:function(event,player,name){
					return player.isUnseen(2)&&get.mode()!='guozhan';
				},
				content:function(){
					player.showCharacter(2);
					player.removeSkill('g_hidden_ai');
				},
			},
			_kamisha:{
				trigger:{source:'damageBegin2'},
				//forced:true,
				popup:false,
				prompt:function(event,player){
					return '是否防止即将对'+get.translation(event.player)+'造成的伤害,改为令其减少'+get.cnNumber(event.num)+'点体力上限?';
				},
				filter:function(event,player){
					return event.hasNature('kami')&&event.num>0;
				},
				ruleSkill:true,
				check:function(event,player){
					var att=get.attitude(player,event.player);
					if(event.player.hp==event.player.maxHp) return att<0;
					if(event.player.hp==event.player.maxHp-1&&
						(event.player.maxHp<=3||event.player.hasSkillTag('maixie'))) return att<0;
					return att>0;
				},
				content:function(){
					trigger.cancel();
					trigger.player.loseMaxHp(trigger.num).source=player;
				},
			},
			aozhan:{
				charlotte:true,
				mod:{
					targetEnabled:function(card){
						if(card.name=='tao'&&(card.isCard&&card.cardid||get.itemtype(card)=='card')) return false;
					},
					cardSavable:function(card){
						if(card.name=='tao'&&(card.isCard&&card.cardid||get.itemtype(card)=='card')) return false;
					},
				},
				group:["aozhan_sha","aozhan_shan"],
				subSkill:{
					sha:{
						enable:["chooseToUse","chooseToRespond"],
						filterCard:{
							name:"tao",
						},
						viewAs:{
							name:"sha",
							isCard:true,
						},
						viewAsFilter:function (player){
							if(!player.countCards('hs','tao')) return false;
						},
						position:'hs',
						prompt:"将一张桃当杀使用或打出",
						check:function (){return 1},
						ai:{
							respondSha:true,
							skillTagFilter:function(player){
								if(!player.countCards('hs','tao')) return false;
							},
							order:function(){
								return get.order({name:'sha'})-0.1;
							},
						},
						sub:true,
					},
					shan:{
						enable:["chooseToRespond","chooseToUse"],
						filterCard:{
							name:"tao",
						},
						viewAs:{
							name:"shan",
							isCard:true,
						},
						prompt:"将一张桃当闪打出",
						check:function (){return 1},
						viewAsFilter:function (player){
							if(!player.countCards('hs','tao')) return false;
						},
						position:'hs',
						ai:{
							respondShan:true,
							skillTagFilter:function(player){
								if(!player.countCards('hs','tao')) return false;
							},
						},
						sub:true,
					},
				},
			},
			global:[],
			globalmap:{},
			storage:{},
			undist:{},
			others:{},
			zhu:{},
			zhuSkill:{},
			land_used:{},
			unequip:{ai:{unequip:true}},
			subplayer:{
				trigger:{player:'dieBefore'},
				forced:true,
				priority:-9,
				onremove:true,
				mark:'character',
				intro:{
					content:function(storage,player){
						if(typeof storage.intro2=='string') return storage.intro2;
						if(typeof storage.intro2=='function') return storage.intro2(storage,player);
						return '死亡前切换回主武将'
					},
					name:function(storage){
						return get.rawName(storage.name);
					}
				},
				content:function(){
					trigger.cancel();
					var evt=trigger.getParent('damage');
					if(evt.player==player){
						evt.untrigger(false,player);
					}
					player.exitSubPlayer(true);
				},
				ai:{
					nosave:true
				}
			},
			autoswap:{
				firstDo:true,
				trigger:{player:['playercontrol','chooseToUseBegin','chooseToRespondBegin','chooseToDiscardBegin','chooseToCompareBegin',
				'chooseButtonBegin','chooseCardBegin','chooseTargetBegin','chooseCardTargetBegin','chooseControlBegin',
				'chooseBoolBegin','choosePlayerCardBegin','discardPlayerCardBegin','gainPlayerCardBegin','chooseToMoveBegin','chooseToPlayBeatmapBegin']},
				forced:true,
				priority:100,
				forceDie:true,
				popup:false,
				filter:function(event,player){
					if(event.autochoose&&event.autochoose()) return false;
					if(lib.filter.wuxieSwap(event)) return false;
					if(_status.auto||!player.isUnderControl()) return false;
					return true;
				},
				content:function(){
					game.swapPlayerAuto(player);
				},
			},
			dualside:{
				charlotte:true,
				subSkill:{
					turn:{
						trigger:{player:['turnOverAfter','dieBefore']},
						silent:true,
						filter:function(event,player){
							if(player.storage.dualside_over) return false;
							return Array.isArray(player.storage.dualside);
						},
						content:function(){
							var cfg=player.storage.dualside;
							var bool=player.isTurnedOver();
							if(trigger.name=='die'){
								bool=!bool;
							}
							if(bool){
								cfg[1]=player.hp;
								cfg[2]=player.maxHp;
								player.reinit(cfg[0],cfg[3],[cfg[4],cfg[5]]);
								player.unmarkSkill('dualside');
								player.markSkillCharacter('dualside',{name:cfg[0]},'正面','当前体力:'+cfg[1]+'/'+cfg[2]);
							}
							else{
								cfg[4]=player.hp;
								cfg[5]=player.maxHp;
								player.reinit(cfg[3],cfg[0],[cfg[1],cfg[2]]);
								player.unmarkSkill('dualside');
								player.markSkillCharacter('dualside',{name:cfg[3]},'背面','当前体力:'+cfg[4]+'/'+cfg[5]);
							}

							if(trigger.name=='die'){
								trigger.cancel();
								delete player.storage.dualside;
								player.storage.dualside_over=true;
								player.unmarkSkill('dualside');
							}
						}
					},
					init:{
						trigger:{global:'gameStart',player:'enterGame'},
						silent:true,
						content:function(){
							var list=[player.name,player.name1,player.name2];
							for(var i=0;i<list.length;i++){
								if(list[i]&&lib.character[list[i]]){
									var info=lib.character[list[i]];
									if(info[3].contains('dualside')&&info[4]){
										player.storage.dualside=[list[i],player.hp,player.maxHp];
										for(var j=0;j<info[4].length;j++){
											if(info[4][j].startsWith('dualside:')){
												var name2=info[4][j].slice(9);
												var info2=lib.character[name2];
												player.storage.dualside.push(name2);
												player.storage.dualside.push(get.infoHp(info2[2]));
												player.storage.dualside.push(get.infoMaxHp(info2[2]));
											}
										}
									}
								}
							}
							var cfg=player.storage.dualside;
							if(get.mode()=='guozhan'){
								if(player.name1==cfg[0]){
									player.showCharacter(0);
								}
								else{
									player.showCharacter(1);
								}
							}
							player.markSkillCharacter('dualside',{name:cfg[3]},'背面','当前体力:'+cfg[4]+'/'+cfg[5]);
						}
					}
				},
				group:['dualside_init','dualside_turn']
			},
			fengyin:{
				init:function(player,skill){
					player.addSkillBlocker(skill);
				},
				onremove:function(player,skill){
					player.removeSkillBlocker(skill);
				},
				charlotte:true,
				skillBlocker:function(skill,player){
					return !lib.skill[skill].charlotte&&!get.is.locked(skill,player);
				},
				mark:true,
				intro:{
					content:function(storage,player,skill){
						var list=player.getSkills(null,false,false).filter(function(i){
							return lib.skill.fengyin.skillBlocker(i,player);
						});
						if(list.length) return '失效技能:'+get.translation(list);
						return '无失效技能';
					}
				}
			},
			baiban:{
				init:function(player,skill){
					player.addSkillBlocker(skill);
				},
				onremove:function(player,skill){
					player.removeSkillBlocker(skill);
				},
				charlotte:true,
				skillBlocker:function(skill,player){
					return !lib.skill[skill].charlotte;
				},
				mark:true,
				intro:{
					content:function(storage,player,skill){
						var list=player.getSkills(null,false,false).filter(function(i){
							return lib.skill.baiban.skillBlocker(i,player);
						});
						if(list.length) return '失效技能:'+get.translation(list);
						return '无失效技能';
					}
				}
			},
			qianxing:{
				mark:true,
				nopop:true,
				init:function(player){
					game.log(player,'获得了','【潜行】');
				},
				intro:{
					content:'锁定技,你不能成为其他角色的卡牌的目标'
				},
				mod:{
					targetEnabled:function(card,player,target){
						if(player!=target) return false;
					}
				}
			},
			mianyi:{
				trigger:{player:'damageBefore'},
				mark:true,
				forced:true,
				init:function(player){
					game.log(player,'获得了','【免疫】');
				},
				content:function(){
					trigger.cancel();
				},
				ai:{
					nofire:true,
					nothunder:true,
					nodamage:true,
					effect:{
						target:function(card,player,target,current){
							if(get.tag(card,'damage')) return [0,0];
						}
					},
				},
				intro:{
					content:'防止一切伤害'
				}
			},
			mad:{
				mark:true,
				locked:true,
				intro:{
					content:'已进入混乱状态',
					name:'混乱',
					onunmark:function(storage,player){
						game.log(player,'解除混乱状态');
					}
				}
			},
			ghujia:{
				intro:{
					content:function(content,player){
						return '已有'+get.cnNumber(player.hujia)+'点护甲值';
					}
				},
				markimage:'image/card/shield.png',
			},
			counttrigger:{
				trigger:{global:'phaseAfter'},
				silent:true,
				charlotte:true,
				priority:-100,
				content:function(){
					player.removeSkill('counttrigger');
					delete player.storage.counttrigger;
				},
				group:'counttrigger_2',
				subSkill:{
					2:{
						trigger:{global:'phaseBefore'},
						silent:true,
						charlotte:true,
						priority:100,
						content:function(){
							player.removeSkill('counttrigger');
							delete player.storage.counttrigger;
						},
					}
				}
			},
			_recovercheck:{
				trigger:{player:'recoverBefore'},
				forced:true,
				priority:100,
				firstDo:true,
				popup:false,
				filter:function(event,player){
					return player.hp>=player.maxHp;
				},
				content:function(){
					trigger.cancel();
				},
			},
			/**
			 * @deprecated
			 */
			/*_turnover:{
				trigger:{player:'phaseBefore'},
				forced:true,
				forceOut:true,
				priority:100,
				popup:false,
				firstDo:true,
				content:function(){
					if(player.isTurnedOver()&&!trigger._noTurnOver){
						trigger.cancel();
						player.turnOver();
						player.phaseSkipped=true;
					}
					else{
						player.phaseSkipped=false;
					}
					var isRound=false;
					if(!trigger.skill){
						isRound=_status.roundSkipped;
						if(_status.isRoundFilter){
							isRound=_status.isRoundFilter(trigger,player);
						}
						else if(_status.seatNumSettled){
							var seatNum=player.getSeatNum();
							if(seatNum!=0){
								if(typeof _status.lastSeatNum!='number'||seatNum<_status.lastSeatNum) isRound=true;
								_status.lastSeatNum=seatNum;
							}
						}
						else if(player==_status.roundStart) isRound=true;
						if(isRound){
							delete _status.roundSkipped;
							game.roundNumber++;
							trigger._roundStart=true;
							game.updateRoundNumber();
							for(var i=0;i<game.players.length;i++){
								if(game.players[i].isOut()&&game.players[i].outCount>0){
									game.players[i].outCount--;
									if(game.players[i].outCount==0&&!game.players[i].outSkills){
										game.players[i].in();
									}
								}
							}
							event.trigger('roundStart');
						}
					}
					_status.globalHistory.push({
						cardMove:[],
						custom:[],
						useCard:[],
						changeHp:[],
						everything:[],
					});
					var players=game.players.slice(0).concat(game.dead);
					for(var i=0;i<players.length;i++){
						var current=players[i];
						current.actionHistory.push({useCard:[],respond:[],skipped:[],lose:[],gain:[],sourceDamage:[],damage:[],custom:[],useSkill:[]});
						current.stat.push({card:{},skill:{}});
						if(isRound){
							current.getHistory().isRound=true;
							current.getStat().isRound=true;
						}
					};
					if(!player.phaseSkipped){
						player.getHistory().isMe=true;
						player.getStat().isMe=true;
					}
					if(isRound){
						game.getGlobalHistory().isRound=true;
					}
				},
			},*/
			_usecard:{
				trigger:{global:'useCardAfter'},
				forced:true,
				popup:false,
				priority:-100,
				lastDo:true,
				filter:function(event){
					return !event._cleared&&event.card.name!='wuxie';
				},
				content:function(){
					game.broadcastAll(function(){
						ui.clear();
					});
					event._cleared=true;
				}
			},
			_discard:{
				trigger:{global:['discardAfter','loseToDiscardpileAfter','loseAsyncAfter']},
				forced:true,
				popup:false,
				priority:-100,
				lastDo:true,
				filter:function(event){
					return ui.todiscard[event.discardid]?true:false;
				},
				content:function(){
					game.broadcastAll(function(id){
						var todiscard=ui.todiscard[id];
						delete ui.todiscard[id];
						if(todiscard){
							var time=1000;
							if(typeof todiscard._discardtime=='number'){
								time+=todiscard._discardtime-get.time();
							}
							if(time<0){
								time=0;
							}
							setTimeout(function(){
								for(var i=0;i<todiscard.length;i++){
									todiscard[i].delete();
								}
							},time);
						}
					},trigger.discardid);
				}
			},
			_save:{
				//trigger:{source:'dying2',player:'dying2'},
				priority:5,
				forced:true,
				popup:false,
				filter:function(event,player){
					//if(!event.player.isDying()) return false;
					//if(event.source&&event.source.isIn()&&event.source!=player) return false;
					//return true;
					return false;
				},
				content:function(){
					"step 0"
					event.dying=trigger.player;
					if(!event.acted) event.acted=[];
					"step 1"
					if(trigger.player.isDead()){
						event.finish();
						return;
					}
					event.acted.push(player);
					var str=get.translation(trigger.player)+'濒死,是否帮助?';
					var str2='当前体力:'+trigger.player.hp;
					if(lib.config.tao_enemy&&event.dying.side!=player.side&&lib.config.mode!='identity'&&lib.config.mode!='guozhan'&&!event.dying.hasSkillTag('revertsave')){
						event._result={bool:false}
					}
					else if(player.canSave(event.dying)){
						player.chooseToUse({
							filterCard:function(card,player,event){
								event=event||_status.event;
								return lib.filter.cardSavable(card,player,event.dying);
							},
							filterTarget:function(card,player,target){
								if(target!=_status.event.dying) return false;
								if(!card) return false;
								var info=get.info(card);
								if(!info.singleCard||ui.selected.targets.length==0){
									var mod=game.checkMod(card,player,target,'unchanged','playerEnabled',player);
									if(mod==false) return false;
									var mod=game.checkMod(card,player,target,'unchanged','targetEnabled',target);
									if(mod!='unchanged') return mod;
								}
								return true;
							},
							prompt:str,
							prompt2:str2,
							ai1:function(card){
								if(typeof card=='string'){
									var info=get.info(card);
									if(info.ai&&info.ai.order){
										if(typeof info.ai.order=='number'){
											return info.ai.order;
										}
										else if(typeof info.ai.order=='function'){
											return info.ai.order();
										}
									}
								}
								return 1;
							},
							ai2:get.effect_use,
							type:'dying',
							targetRequired:true,
							dying:event.dying
						});
					}
					else{
						event._result={bool:false}
					}
					"step 2"
					if(result.bool){
						var player=trigger.player;
						if(player.hp<=0&&!trigger.nodying&&!player.nodying&&player.isAlive()&&!player.isOut()&&!player.removed) event.goto(0);
						else trigger.untrigger();
					}
					else{
						for(var i=0;i<20;i++){
							if(event.acted.contains(event.player.next)){
								break;
							}
							else{
								event.player=event.player.next;
								if(!event.player.isOut()){
									event.goto(1);
									break;
								}
							}
						}
					}
				}
			},
			_ismin:{
				mod:{
					cardEnabled:function(card,player){
						if(player.isMin()){
							if(get.type(card)=='equip') return false;
						}
					}
				}
			},
			_recasting:{
				enable:'phaseUse',
				logv:false,
				prompt:'将要重铸的牌置入弃牌堆并摸一张牌',
				filter:(event,player)=>player.hasCard(card=>lib.skill._recasting.filterCard(card,player),lib.skill._recasting.position),
				position:'he',
				filterCard:(card,player)=>player.canRecast(card,null,true),
				discard:false,
				lose:false,
				delay:false,
				content:()=>{
					player.recast(cards,null,(player,cards)=>{
						var numberOfCardsToDraw=cards.length;
						cards.forEach(value=>{
							if(lib.config.mode=='stone'&&_status.mode=='deck'&&!player.isMin()&&get.type(value).startsWith('stone')){
								var stonecard=get.stonecard(1,player.career);
								if(stonecard.length){
									numberOfCardsToDraw-=stonecard.length;
									player.gain(game.createCard(stonecard.randomGet()),'draw');
								}
								else player.draw({
									drawDeck:1
								}).log=false;
							}
							else if(get.subtype(value)=='spell_gold'){
								var libCard=get.libCard(info=>info.subtype=='spell_silver');
								if(!libCard.length) return;
								numberOfCardsToDraw--;
								player.gain(game.createCard(libCard.randomGet()),'draw');
							}
							else if(get.subtype(value)=='spell_silver'){
								var libCard=get.libCard(info=>info.subtype=='spell_bronze');
								if(!libCard.length) return;
								numberOfCardsToDraw--;
								player.gain(game.createCard(libCard.randomGet()),'draw');
							}
						});
						if(numberOfCardsToDraw) player.draw(numberOfCardsToDraw).log=false;
					});
				},
				ai:{
					basic:{
						order:6
					},
					result:{
						player:1
					}
				}
			},
			_lianhuan:{
				trigger:{player:'damageAfter'},
				filter:function(event,player){
					return event.lianhuanable==true;
				},
				forced:true,
				popup:false,
				logv:false,
				forceDie:true,
				//priority:-5,
				content:function(){
					"step 0"
					event.logvid=trigger.getLogv();
					"step 1"
					event.targets=game.filterPlayer(function(current){
						return current!=event.player&&current.isLinked();
					});
					lib.tempSortSeat=_status.currentPhase||player;
					event.targets.sort(lib.sort.seat);
					delete lib.tempSortSeat;
					event._args=[trigger.num,trigger.nature,trigger.cards,trigger.card];
					if(trigger.source) event._args.push(trigger.source);
					else event._args.push("nosource");
					"step 2"
					if(event.targets.length){
						var target=event.targets.shift();
						if(target.isLinked()) target.damage.apply(target,event._args.slice(0));
						event.redo();
					}
				},
			},
			_lianhuan4:{
				trigger:{player:'changeHp'},
				priority:-10,
				forced:true,
				popup:false,
				forceDie:true,
				filter:function(event,player){
					var evt=event.getParent();
					return evt&&evt.name=='damage'&&evt.hasNature('linked')&&player.isLinked();
				},
				content:function(){
					player.link();
					if(trigger.getParent().notLink()) trigger.getParent().lianhuanable=true;
				}
			},
			/**
			 * @deprecated
			 */
			_chongzhu:{
				get filter(){
					return lib.skill._recasting.filter;
				},
				set filter(filter){
					lib.skill._recasting.filter=filter;
				},
				get filterCard(){
					return lib.skill._recasting.filterCard;
				},
				set filterCard(filterCard){
					lib.skill._recasting.filterCard=filterCard;
				},
				get content(){
					return lib.skill._recasting.content;
				},
				set content(content){
					lib.skill._recasting.content=content;
				},
				get ai(){
					return lib.skill._recasting.ai;
				},
				set ai(ai){
					lib.skill._recasting.ai=ai;
				}
			}
		},
		character:{},
		perfectPair:{},
		cardPile:{},
		message:{
			server:{
				init:function(version,config,banned_info){
					if(lib.node.banned.contains(banned_info)){
						this.send('denied','banned');
					}
					else if(config.id&&lib.playerOL&&lib.playerOL[config.id]){
						var player=lib.playerOL[config.id];
						player.setNickname();
						player.ws=this;
						player.isAuto=false;
						this.id=config.id;
						game.broadcast(function(player){
							player.setNickname();
						},player);
						this.send('reinit',lib.configOL,get.arenaState(),game.getState?game.getState():{},game.ip,null,_status.onreconnect,_status.cardtag,_status.postReconnect);
					}
					else if(version!=lib.versionOL){
						this.send('denied','version');
						lib.node.clients.remove(this);
						this.closed=true;
					}
					else if(!_status.waitingForPlayer){
						if(game.phaseNumber&&lib.configOL.observe){
							lib.node.observing.push(this);
							this.send('reinit',lib.configOL,get.arenaState(),game.getState?game.getState():{},game.ip,game.players[0].playerid,null,_status.cardtag);
							if(!ui.removeObserve){
								ui.removeObserve=ui.create.system('移除旁观',function(){
									lib.configOL.observe=false;
									if(game.onlineroom){
										game.send('server','config',lib.configOL);
									}
									while(lib.node.observing.length){
										lib.node.observing.shift().ws.close();
									}
									this.remove();
									delete ui.removeObserve;
								},true,true);
							}
						}
						else{
							this.send('denied','gaming');
							lib.node.clients.remove(this);
							this.closed=true;
						}
					}
					else if(lib.node.clients.length-(window.isNonameServer?1:0)>=parseInt(lib.configOL.number)){
						this.send('denied','number');
						lib.node.clients.remove(this);
						this.closed=true;
					}
					else{
						if(config){
							this.avatar=config.avatar;
							this.nickname=config.nickname;
						}
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].classList.contains('unselectable2')) continue;
							if(game.connectPlayers[i]!=game.me&&!game.connectPlayers[i].playerid){
								game.connectPlayers[i].playerid=this.id;
								game.connectPlayers[i].initOL(this.nickname,this.avatar);
								game.connectPlayers[i].ws=this;
								break;
							}
						}
						this.send('init',this.id,lib.configOL,game.ip,window.isNonameServer,game.roomId);
					}
				},
				inited:function(){
					this.inited=true;
					if(_status.waitingForPlayer){
						game.updateWaiting();
					}
				},
				reinited:function(){
					this.inited=true;
				},
				result:function(result){
					if(lib.node.observing.contains(this)) return;
					var player=lib.playerOL[this.id];
					if(player){
						player.unwait(result);
					}
				},
				tempResult:function(result){
					if(lib.node.observing.contains(this)) return;
					var player=lib.playerOL[this.id];
					if(player){
						player.tempUnwait(result);
					}
				},
				startGame:function(){
					if(this.id==game.onlinezhu){
						game.resume();
					}
				},
				changeRoomConfig:function(config){
					if(this.id==game.onlinezhu){
						game.broadcastAll(function(config){
							for(var i in config){
								lib.configOL[i]=config[i];
							}
							if(ui.connectStartBar){
								ui.connectStartBar.firstChild.innerHTML=get.modetrans(lib.configOL,true);
							}
						},config);
						if(lib.configOL.mode=='identity'&&lib.configOL.identity_mode=='zhong'&&game.connectPlayers){
							for(var i=0;i<game.connectPlayers.length;i++){
								game.connectPlayers[i].classList.remove('unselectable2');
							}
							lib.configOL.number=8;
							game.updateWaiting();
						}
						if(game.onlineroom){
							game.send('server','config',lib.configOL);
						}
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].playerid==this.id){
								game.connectPlayers[i].chat('房间设置已更改');
							}
						}
					}
				},
				changeNumConfig:function(num,index,bool){
					if(this.id==game.onlinezhu){
						lib.configOL.number=num;
						game.send('server','config',lib.configOL);
						if(game.connectPlayers&&game.connectPlayers[index]){
							if(bool){
								game.connectPlayers[index].classList.add('unselectable2');
							}
							else{
								game.connectPlayers[index].classList.remove('unselectable2');
							}
							game.updateWaiting();
						}
					}
				},
				throwEmotion:function(target,emotion){
					if(lib.node.observing.contains(this)) return;
					var player=lib.playerOL[this.id];
					if(player){
						player.throwEmotion(target,emotion);
					}
				},
				emotion:function(id,pack,emotion){
					if(lib.node.observing.contains(this)) return;
					var that=this;
					if(!this.id||(!lib.playerOL[this.id]&&(!game.connectPlayers||!function(){
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].playerid==that.id){
								return true;
							}
						}
						return false;
					}()))) return;
					var player;
					if(lib.playerOL[id]){
						player=lib.playerOL[id];
					}
					else if(game.connectPlayers){
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].playerid==id){
								player=game.connectPlayers[i];break;
							}
						}
					}
					if(player) lib.element.player.emotion.apply(player,[pack,emotion]);
				},
				chat:function(id,str){
					if(lib.node.observing.contains(this)) return;
					var that=this;
					if(!this.id||(!lib.playerOL[this.id]&&(!game.connectPlayers||!function(){
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].playerid==that.id){
								return true;
							}
						}
						return false;
					}()))) return;
					var player;
					if(lib.playerOL[id]){
						player=lib.playerOL[id];
					}
					else if(game.connectPlayers){
						for(var i=0;i<game.connectPlayers.length;i++){
							if(game.connectPlayers[i].playerid==id){
								player=game.connectPlayers[i];break;
							}
						}
					}
					if(player) lib.element.player.chat.call(player,str);
				},
				giveup:function(player){
					if(lib.node.observing.contains(this)||!player||!player._giveUp) return;
					_status.event.next.length=0;
					game.createEvent('giveup',false).set('includeOut',true).setContent(function(){
						game.log(player,'投降');
						player.popup('投降');
						player.die('nosource').includeOut=true;
					}).player=player;
				},
				auto:function(){
					if(lib.node.observing.contains(this)) return;
					var player=lib.playerOL[this.id];
					if(player){
						player.isAuto=true;
						player.setNickname(player.nickname+' - 托管');
						game.broadcast(function(player){
							player.setNickname(player.nickname+' - 托管');
						},player);
					}
				},
				unauto:function(){
					if(lib.node.observing.contains(this)) return;
					var player=lib.playerOL[this.id];
					if(player){
						player.isAuto=false;
						player.setNickname(player.nickname);
						game.broadcast(function(player){
							player.setNickname(player.nickname);
						},player);
					}
				},
				exec:function(func){
					// if(typeof func=='function'){
					//     var args=Array.from(arguments);
					//     args.shift();
					//     func.apply(this,args);
					// }
				},
				log:function(){
					var items=[];
					try{
						for(var i=0;i<arguments.length;i++){
							eval('items.push('+arguments[i]+')');
						}
					}
					catch(e){
						this.send('log',['err']);
						return;
					}
					this.send('log',items);
				}
			},
			client:{
				log:function(arr){
					if(Array.isArray(arr)){
						for(var i=0;i<arr.length;i++){
							console.log(arr[i]);
						}
					}
				},
				opened:function(){
					game.send('init',lib.versionOL,{
						id:game.onlineID,
						avatar:lib.config.connect_avatar,
						nickname:get.connectNickname()
					},lib.config.banned_info);
					if(ui.connecting&&!ui.connecting.splashtimeout){
						ui.connecting.firstChild.innerHTML='重连成功';
					}
				},
				onconnection:function(id){
					var ws={wsid:id};
					for(var i in lib.element.nodews){
						ws[i]=lib.element.nodews[i];
					}
					lib.wsOL[id]=ws;
					lib.init.connection(ws);
				},
				onmessage:function(id,message){
					if(lib.wsOL[id]){
						lib.wsOL[id].onmessage(message);
					}
				},
				onclose:function(id){
					if(lib.wsOL[id]){
						lib.wsOL[id].onclose();
					}
				},
				selfclose:function(){
					if(game.online||game.onlineroom){
						if((game.servermode||game.onlinehall)&&_status.over){
							// later
						}
						else{
							game.saveConfig('tmp_user_roomId');
						}
					}
					game.ws.close();
				},
				reloadroom:function(forced){
					if(window.isNonameServer&&(forced||!_status.protectingroom)){
						game.reload();
					}
				},
				createroom:function(index,config,mode){
					game.online=false;
					game.onlineroom=true;
					game.roomId=index;
					lib.node={};
					if(config&&mode&&window.isNonameServer){
						if(mode=='auto'){
							mode=lib.configOL.mode;
						}
						game.switchMode(mode,config);
					}
					else{
						game.switchMode(lib.configOL.mode);
					}
					ui.create.connecting(true);
				},
				enterroomfailed:function(){
					alert('请稍后再试');
					_status.enteringroom=false;
					ui.create.connecting(true);
				},
				roomlist:function(list,events,clients,wsid){
					game.send('server','key',[game.onlineKey,lib.version]);
					game.online=true;
					game.onlinehall=true;
					lib.config.recentIP.remove(_status.ip);
					lib.config.recentIP.unshift(_status.ip);
					lib.config.recentIP.splice(5);
					if(!lib.config.reconnect_info||lib.config.reconnect_info[0]!=_status.ip){
						game.saveConfig('reconnect_info',[_status.ip,null]);
					}
					game.saveConfig('recentIP',lib.config.recentIP);
					_status.connectMode=true;

					game.clearArena();
					game.clearConnect();
					ui.pause.hide();
					ui.auto.hide();

					clearTimeout(_status.createNodeTimeout);
					game.send('server','changeAvatar',get.connectNickname(),lib.config.connect_avatar);

					var proceed=function(){
						game.ip=get.trimip(_status.ip);
						ui.create.connectRooms(list);
						if(events){
							ui.connectEvents=ui.create.div('.forceopaque.menubutton.large.connectevents.pointerdiv','约战',ui.window,ui.click.connectEvents);
							ui.connectEventsCount=ui.create.div('.forceopaque.menubutton.icon.connectevents.highlight.hidden','',ui.window);
							ui.connectClients=ui.create.div('.forceopaque.menubutton.large.connectevents.pointerdiv.left','在线',ui.window,ui.click.connectClients);
							ui.connectClientsCount=ui.create.div('.forceopaque.menubutton.icon.connectevents.highlight.left','1',ui.window);
							ui.createRoomButton=ui.create.div('.forceopaque.menubutton.large.connectevents.pointerdiv.left2','创建房间',ui.window,function(){
								if(!_status.creatingroom){
									_status.creatingroom=true;
									ui.click.connectMenu();
								}
							});
							if(events.length){
								ui.connectEventsCount.innerHTML=events.filter(function(evt){
									return evt.creator==game.onlineKey||!get.is.banWords(evt.content)
								}).length;
								ui.connectEventsCount.show();
							}
						}
						game.wsid=wsid;
						lib.message.client.updaterooms(list,clients);
						lib.message.client.updateevents(events);
						ui.exitroom=ui.create.system('退出房间',function(){
							game.saveConfig('tmp_owner_roomId');
							game.saveConfig('tmp_user_roomId');
							if(ui.rooms){
								game.saveConfig('reconnect_info');
							}
							else{
								if(lib.config.reconnect_info){
									lib.config.reconnect_info.length=1;
									game.saveConfig('reconnect_info',lib.config.reconnect_info);
								}
							}
							game.reload();
						},true);

						var findRoom=function(id){
							for(var room of ui.rooms){
								if(room.key==id) return room;
							}
							return false;
						};
						if(typeof lib.config.tmp_owner_roomId=='string'){
							if(typeof game.roomId!='string'&&!findRoom(lib.config.tmp_owner_roomId)){
								lib.configOL.mode=lib.config.connect_mode;
								game.roomId=lib.config.tmp_owner_roomId;
							}
							game.saveConfig('tmp_owner_roomId');
						}
						if(typeof lib.config.tmp_user_roomId=='string'){
							if(typeof game.roomId!='string'){
								if(findRoom(lib.config.tmp_user_roomId)){
									game.roomId=lib.config.tmp_user_roomId;
								}
								else{
									ui.create.connecting();
									(function(){
										var n=10;
										var id=lib.config.tmp_user_roomId;
										var interval=setInterval(function(){
											if(n>0){
												n--;
												if(findRoom(id)){
													clearInterval(interval);
													game.send('server','enter',id,get.connectNickname(),lib.config.connect_avatar);
												}
											}
											else{
												ui.create.connecting(true);
												clearInterval(interval);
											}
										},500);
									}());
								}
							}
							game.saveConfig('tmp_user_roomId');
						}

						if(window.isNonameServer){
							var cfg='pagecfg'+window.isNonameServer;
							if(lib.config[cfg]){
								lib.configOL=lib.config[cfg][0];
								game.send('server','server',lib.config[cfg].slice(1));
								game.saveConfig(cfg);
								_status.protectingroom=true;
								setTimeout(function(){
									_status.protectingroom=false;
									if(!lib.node||!lib.node.clients||!lib.node.clients.length){
										game.reload();
									}
								},15000);
							}
							else{
								game.send('server','server');
							}
						}
						else if(typeof game.roomId=='string'){
							var room=findRoom(game.roomId);
							if(game.roomIdServer&&room&&(room.serving||!room.version)){
								console.log();
								if(lib.config.reconnect_info){
									lib.config.reconnect_info[2]=null;
									game.saveConfig('reconnect_info',lib.config.reconnect_info);
								}
							}
							else{
								ui.create.connecting();
								game.send('server',(game.roomId==game.onlineKey)?'create':'enter',game.roomId,get.connectNickname(),lib.config.connect_avatar);
							}
						}
						lib.init.onfree();
					}
					if(_status.event.parent){
						game.forceOver('noover',proceed);
					}
					else{
						proceed();
					}
				},
				updaterooms:function(list,clients){
					if(ui.rooms){
						var map={},map2={};
						for(var i of ui.rooms) map2[i.key]=true;
						for(var i of list){
							if(!i) continue;
							map[i[4]]=i;
						}
						ui.window.classList.add('more_room');
						for(var i=0;i<ui.rooms.length;i++){
							if(!map[ui.rooms[i].key]){
								ui.rooms[i].remove();
								ui.rooms.splice(i--,1);
							}
							else ui.rooms[i].initRoom(list[i]);
						}
						for(var i of list){
							if(!i) continue;
							map[i[4]]=i;
							if(!map2[i[4]]){
								var player=ui.roombase.add('<div class="popup text pointerdiv" style="width:calc(100% - 10px);display:inline-block;white-space:nowrap">空房间</div>');
								player.roomindex=i;
								player.initRoom=lib.element.player.initRoom;
								player.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.connectroom);
								player.initRoom(i);
								ui.rooms.push(player);
							}
						}
					}
					lib.message.client.updateclients(clients,true);
				},
				updateclients:function(clients,bool){
					if(clients&&ui.connectClients){
						ui.connectClients.info=clients;
						ui.connectClientsCount.innerHTML=clients.length;
					}
					if(_status.connectClientsCallback){
						_status.connectClientsCallback();
					}
				},
				updateevents:function(events){
					if(events&&ui.connectEvents){
						ui.connectEvents.info=events;
						var num=events.filter(function(evt){
							return typeof evt.creator=='string'&&(evt.creator==game.onlineKey||!get.is.banWords(evt.content))
						}).length;
						if(num){
							ui.connectEventsCount.innerHTML=num;
							ui.connectEventsCount.show();
						}
						else{
							ui.connectEventsCount.hide();
						}
						if(_status.connectEventsCallback){
							_status.connectEventsCallback();
						}
					}
				},
				eventsdenied:function(reason){
					var str='创建约战失败';
					if(reason=='total'){
						str+=',约战总数不能超过20';
					}
					else if(reason=='time'){
						str+=',时间已过';
					}
					else if(reason=='ban'){
						str+=',请注意文明发言';
					}
					alert(str);
				},
				init:function(id,config,ip,servermode,roomId){
					game.online=true;
					game.onlineID=id;
					game.ip=ip;
					game.servermode=servermode;
					game.roomId=roomId;
					if(game.servermode){
						game.saveConfig('reconnect_info',[_status.ip,id,game.roomId]);
					}
					else{
						game.saveConfig('reconnect_info',[_status.ip,id]);
						game.saveConfig('tmp_user_roomId',roomId);
					}
					lib.config.recentIP.remove(_status.ip);
					lib.config.recentIP.unshift(_status.ip);
					lib.config.recentIP.splice(5);
					game.saveConfig('recentIP',lib.config.recentIP);
					_status.connectMode=true;
					lib.configOL=config;
					lib.playerOL={};
					lib.cardOL={};

					game.clearArena();
					game.finishCards();
					ui.create.roomInfo();
					ui.create.chat();
					if(game.servermode){
						ui.create.connectPlayers(get.modetrans(config,true));
					}
					else{
						ui.create.connectPlayers(ip);
					}
					ui.pause.hide();
					ui.auto.hide();
					game.clearConnect();
					clearTimeout(_status.createNodeTimeout);

					var proceed=function(){
						game.loadModeAsync(config.mode,function(mode){
							for(var i in mode.ai){
								if(typeof mode.ai[i]=='object'){
									if(ai[i]==undefined) ai[i]={};
									for(var j in mode.ai[i]){
										ai[i][j]=mode.ai[i][j];
									}
								}
								else{
									ai[i]=mode.ai[i];
								}
							}
							for(var i in mode.get){
								if(typeof mode.get[i]=='object'){
									if(get[i]==undefined) get[i]={};
									for(var j in mode.get[i]){
										get[i][j]=mode.get[i][j];
									}
								}
								else{
									get[i]=mode.get[i];
								}
							}
							for(var i in mode.translate){
								lib.translate[i]=mode.translate[i];
							}
							if(mode.game){
								game.getIdentityList=mode.game.getIdentityList;
								game.updateState=mode.game.updateState;
								game.getRoomInfo=mode.game.getRoomInfo;
							}
							if(mode.element&&mode.element.player){
								for(var i in mode.element.player){
									lib.element.player[i]=mode.element.player[i];
								}
							}
							if(mode.skill){
								for(var i in mode.skill){
									lib.skill[i]=mode.skill[i];
								}
							}
							if(mode.card){
								for(var i in mode.card){
									lib.card[i]=mode.card[i];
								}
							}
							game.finishCards();
							if(mode.characterPack){
								for(var i in mode.characterPack){
									lib.characterPack[i]=mode.characterPack[i];
								}
							}
							_status.event={
								finished:true,
								next:[],
								after:[]
							};
							_status.paused=false;
							game.createEvent('game',false).setContent(lib.init.startOnline);
							game.loop();
							game.send('inited');
							ui.create.connecting(true);
						});
					}
					if(_status.event.parent){
						game.forceOver('noover',proceed);
					}
					else{
						proceed();
					}
					for(var i in lib.characterPack){
						for(var j in lib.characterPack[i]){
							lib.character[j]=lib.character[j]||lib.characterPack[i][j];
						}
					}
				},
				reinit:function(config,state,state2,ip,observe,onreconnect,cardtag,postReconnect){
					ui.auto.show();
					ui.pause.show();
					game.clearConnect();
					clearTimeout(_status.createNodeTimeout);
					game.online=true;
					game.ip=ip;
					game.servermode=state.servermode;
					game.roomId=state.roomId;
					if(state.over){
						_status.over=true;
					}
					if(observe){
						game.observe=true;
						game.onlineID=null;
						game.roomId=null;
					}
					if(game.servermode&&!observe){
						game.saveConfig('reconnect_info',[_status.ip,game.onlineID,game.roomId]);
					}
					else{
						game.saveConfig('reconnect_info',[_status.ip,game.onlineID]);
						if(!observe){
							game.saveConfig('tmp_user_roomId',game.roomId);
						}
					}
					_status.connectMode=true;
					lib.configOL=config;
					lib.playerOL={};
					lib.cardOL={};

					game.loadModeAsync(config.mode,function(mode){
						for(var i in mode.ai){
							if(typeof mode.ai[i]=='object'){
								if(ai[i]==undefined) ai[i]={};
								for(var j in mode.ai[i]){
									ai[i][j]=mode.ai[i][j];
								}
							}
							else{
								ai[i]=mode.ai[i];
							}
						}
						for(var i in mode.get){
							if(typeof mode.get[i]=='object'){
								if(get[i]==undefined) get[i]={};
								for(var j in mode.get[i]){
									get[i][j]=mode.get[i][j];
								}
							}
							else{
								get[i]=mode.get[i];
							}
						}
						for(var i in mode.translate){
							lib.translate[i]=mode.translate[i];
						}
						if(mode.game){
							game.getIdentityList=mode.game.getIdentityList;
							game.getIdentityList2=mode.game.getIdentityList2;
							game.updateState=mode.game.updateState;
							game.showIdentity=mode.game.showIdentity;
						}
						if(mode.element&&mode.element.player){
							for(var i in mode.element.player){
								lib.element.player[i]=mode.element.player[i];
							}
						}
						if(mode.skill){
							for(var i in mode.skill){
								lib.skill[i]=mode.skill[i];
							}
						}
						if(mode.card){
							for(var i in mode.card){
								lib.card[i]=mode.card[i];
							}
						}
						game.finishCards();
						if(mode.characterPack){
							for(var i in mode.characterPack){
								lib.characterPack[i]=mode.characterPack[i];
							}
						}
						if(mode.onreinit){
							mode.onreinit();
						}
						_status.cardtag=get.parsedResult(cardtag);
						game.players=[];
						game.dead=[];
						for(var i in lib.characterPack){
							for(var j in lib.characterPack[i]){
								lib.character[j]=lib.character[j]||lib.characterPack[i][j];
							}
						}
						game.clearArena();
						game.finishCards();
						if(!observe){
							ui.create.chat();
							if(ui.exitroom){
								ui.exitroom.remove();
								delete ui.exitroom;
							}
						}
						else{
							if(!ui.exitroom){
								ui.create.system('退出旁观',function(){
									game.saveConfig('reconnect_info');
									game.reload();
								},true);
							}
							if(!lib.configOL.observe_handcard){
								ui.arena.classList.add('observe');
							}
						}
						postReconnect=get.parsedResult(postReconnect);
						for(var i in postReconnect){
							if(Array.isArray(postReconnect[i])){
								postReconnect[i].shift().apply(this,postReconnect[i]);
							}
						}
						state=get.parsedResult(state);
						ui.arena.setNumber(state.number);
						_status.mode=state.mode;
						_status.renku=state.renku;
						lib.inpile=state.inpile;
						lib.inpile_nature=state.inpile_nature;
						var pos=state.players[observe||game.onlineID].position;
						for(var i in state.players){
							var info=state.players[i];
							var player=ui.create.player(ui.arena).animate('start');
							player.dataset.position=(info.position<pos)?info.position-pos+parseInt(state.number):info.position-pos;
							if(i==observe||i==game.onlineID){
								game.me=player;
							}
							if(player.setModeState){
								player.setModeState(info);
							}
							else{
								player.init(info.name1,info.name2);
								if(info.name&&info.name!=info.name1) player.name=info.name;
							}
							if(!info.unseen) player.classList.remove('unseen');
							if(!info.unseen2) player.classList.remove('unseen2');
							if(!player.isUnseen(2)&&player.storage.nohp){
								delete player.storage.nohp;
								player.node.hp.show();
							}
							player.playerid=i;
							player.nickname=info.nickname;
							player.changeGroup(info.group,false,'nobroadcast');
							player.identity=info.identity;
							player.identityShown=info.identityShown;
							player.hp=info.hp;
							player.maxHp=info.maxHp;
							player.hujia=info.hujia;
							player.sex=info.sex;
							player.side=info.side;
							player.phaseNumber=info.phaseNumber;
							player.seatNum=info.seatNum;
							player.disabledSlots=info.disabledSlots;
							player.expandedSlots=info.expandedSlots;
							player.setNickname();
							if(info.dead){
								player.classList.add('dead');
								if(lib.config.die_move){
									player.$dieflip();
								}
								if(lib.element.player.$dieAfter){
									lib.element.player.$dieAfter.call(player);
								}
								game.dead.push(player);
							}
							else{
								game.players.push(player);
							}
							if(info.linked){
								player.addLink();
							}
							if(info.turnedover){
								player.classList.add('turnedover');
							}
							if(info.out){
								player.classList.add('out');
							}
							if(info.disableJudge){
								player.$disableJudge();
							}
							player.$syncDisable();

							player.directgain(info.handcards);
							lib.playerOL[i]=player;
							for(var i=0;i<info.equips.length;i++){
								player.$equip(info.equips[i]);
							}
							for(var i=0;i<info.handcards.length;i++){
								info.handcards[i].addGaintag(info.gaintag[i]);
							}
							for(var i=0;i<info.specials.length;i++){
								info.specials[i].classList.add('glows');
							}
							if(info.expansions.length){
								var expansion_gaintag=[];
								player.$addToExpansion(info.expansions);
								for(var i=0;i<info.expansions.length;i++){
									info.expansions[i].addGaintag(info.expansion_gaintag[i]);
									expansion_gaintag.addArray(info.expansion_gaintag[i]);
								}
								for(var i of expansion_gaintag) player.markSkill[i];
							}
							for(var i=0;i<info.judges.length;i++){
								if(info.views[i]&&info.views[i]!=info.judges[i]){
									info.judges[i].classList.add('fakejudge');
									info.judges[i].viewAs=info.views[i];
									info.judges[i].node.background.innerHTML=lib.translate[info.views[i]+'_bg']||get.translation(info.views[i])[0]
								}
								player.node.judges.appendChild(info.judges[i]);
							}
							ui.updatej(player);
							if(!player.setModeState){
								if(!game.getIdentityList&&info.identityNode){
									player.node.identity.innerHTML=info.identityNode[0];
									player.node.identity.dataset.color=info.identityNode[1];
								}
								else if(player==game.me||player.identityShown||observe){
									player.setIdentity();
									player.forceShown=true;
								}
								else{
									player.setIdentity('cai');
								}
								if(!lib.configOL.observe_handcard&&(lib.configOL.mode=='identity'||lib.configOL.mode=='guozhan')){
									if(observe&&!player.identityShown){
										player.setIdentity('cai');
										player.forceShown=false;
									}
								}
							}
							player.update();
						}
						game.arrangePlayers();
						ui.create.me(true);

						_status.event={
							finished:true,
							next:[],
							after:[]
						};
						_status.paused=false;
						_status.dying=get.parsedResult(state.dying)||[];

						if(game.updateState){
							game.updateState(state2);
						}
						var next=game.createEvent('game',false);
						next.setContent(lib.init.startOnline);
						if(observe){
							next.custom.replace.target=function(player){
								if(!lib.configOL.observe_handcard&&lib.configOL.mode=='guozhan'){
									return;
								}
								if(player.isAlive()){
									if(!game.me.identityShown&&lib.configOL.mode=='guozhan'){
										game.me.node.identity.firstChild.innerHTML='猜';
										game.me.node.identity.dataset.color='unknown';
									}
									game.swapPlayer(player);
									if(!game.me.identityShown&&lib.configOL.mode=='guozhan'){
										game.me.node.identity.firstChild.innerHTML='';
									}
								}
							}
						}
						else{
							if(Array.isArray(onreconnect)){
								onreconnect.shift().apply(this,onreconnect);
							}
						}
						game.loop();
						game.send('reinited');
						game.showHistory();
						_status.gameStarted=true;
						if(lib.config.show_cardpile){
							ui.cardPileButton.style.display='';
						}
						if(!observe&&game.me&&(game.me.isDead()||_status.over)){
							ui.create.exit();
						}
						ui.updatehl();
						ui.create.connecting(true);
					});
				},
				exec:function(func){
					var key=game.onlineKey;
					if(typeof func=='function'){
						var args=Array.from(arguments);
						args.shift();
						func.apply(this,args);
					}
					if(key){
						game.onlineKey=key;
						localStorage.setItem(lib.configprefix+'key',game.onlineKey);
					}
				},
				denied:function(reason){
					switch(reason){
						case 'version':
							alert('加入失败:版本不匹配,请将游戏更新至最新版');
							game.saveConfig('tmp_owner_roomId');
							game.saveConfig('tmp_user_roomId');
							game.saveConfig('reconnect_info');
							break;
						case 'gaming':alert('加入失败:游戏已开始');break;
						case 'number':alert('加入失败:房间已满');break;
						case 'banned':alert('加入失败:房间拒绝你加入');break;
						case 'key':
							alert('您的游戏版本过低,请升级到最新版');
							game.saveConfig('tmp_owner_roomId');
							game.saveConfig('tmp_user_roomId');
							game.saveConfig('reconnect_info');
							break;
						case 'offline':
						if(_status.paused&&_status.event.name=='game'){
							setTimeout(game.resume,500);
						}
						break;
					}
					game.ws.close();
					if(_status.connectDenied){
						_status.connectDenied();
					}
				},
				cancel:function(id){
					if(_status.event._parent_id==id){
						ui.click.cancel();
					}
					if(_status.event.id==id){
						if(_status.event._backup) ui.click.cancel();
						ui.click.cancel();
						if(ui.confirm){
							ui.confirm.close();
						}
						if(_status.event.result){
							_status.event.result.id=id;
						}
					}
				},
				closeDialog:function(id){
					var dialog=get.idDialog(id);
					if(dialog){
						dialog.close();
					}
				},
				createDialog:function(id){
					var args=Array.from(arguments);
					args.shift();
					ui.create.dialog.apply(this,args).videoId=id;
				},
				gameStart:function(){
					for(var i=0;i<game.connectPlayers.length;i++){
						game.connectPlayers[i].delete();
					}
					delete game.connectPlayers;
					if(ui.connectStartButton){
						ui.connectStartButton.delete();
						delete ui.connectStartButton;
					}
					if(ui.connectStartBar){
						ui.connectStartBar.delete();
						delete ui.connectStartBar;
					}
					if(ui.roomInfo){
						ui.roomInfo.remove();
						delete ui.roomInfo;
					}
					if(ui.exitroom){
						ui.exitroom.remove();
						delete ui.exitroom;
					}
					ui.auto.show();
					ui.pause.show();
					if(lib.config.show_cardpile){
						ui.cardPileButton.style.display='';
					}
					_status.gameStarted=true;
					game.showHistory();
				},
				updateWaiting:function(map){
					if(!game.connectPlayers) return;
					if(!lib.translate.zhu){
						lib.translate.zhu='主';
					}
					game.onlinezhu=false;
					_status.waitingForPlayer=true;
					for(var i=0;i<map.length;i++){
						if(map[i]=='disabled'){
							game.connectPlayers[i].classList.add('unselectable2');
						}
						else{
							game.connectPlayers[i].classList.remove('unselectable2');
							if(map[i]){
								game.connectPlayers[i].initOL(map[i][0],map[i][1]);
								game.connectPlayers[i].playerid=map[i][2];
								if(map[i][3]=='zhu'){
									game.connectPlayers[i].setIdentity('zhu');
									if(map[i][2]==game.onlineID){
										game.onlinezhu=true;
										if(ui.roomInfo){
											ui.roomInfo.innerHTML='房间设置';
										}
										if(ui.connectStartButton){
											ui.connectStartButton.innerHTML='开始游戏';
										}
									}
								}
								else{
									game.connectPlayers[i].node.identity.firstChild.innerHTML='';
								}
							}
							else{
								game.connectPlayers[i].uninitOL();
								delete game.connectPlayers[i].playerid;
							}
						}
					}
				}
			}
		},
		suit:['club','spade','diamond','heart'],
		suits:['club','spade','diamond','heart','none'],
		color:{
			black:['club','spade'],
			red:['diamond','heart'],
			none:['none'],
		},
		group:['wei','shu','wu','qun','jin','shen'],
		//数值代表各元素在名称中排列的先后顺序
		nature:new Map([
			['fire',20],
			['thunder',30],
			['kami',60],
			['ice',40],
			['stab',10],
			['poison',50]
		]),
		linked:['fire','thunder','kami','ice'],
		natureBg:new Map([
			['stab','image/card/cisha.png']
		]),
		natureSeparator:'|',
		namePrefix:new Map([
			['界',{
				color:'#fdd559',
				nature:'soilmm',
			}],
			['谋',{
				color:'#def7ca',
				nature:'woodmm',
			}],
			['武',{
				color:'#fd8359',
				nature:'soilmm',
			}],
			['乐',{
				color:'#f7f4fc',
				nature:'keymm',
			}],
			['神',{
				color:'#faecd1',
				nature:'orangemm',
			}],
			['族',{
				color:'#ee9ac7',
				nature:'firemm',
			}],
			['晋',{
				color:'#f3c5ff',
				nature:'blackmm',
			}],
			['侠',{
				color:'#eeeeee',
				nature:'qunmm',
			}],
			['起',{
				color:'#c3f9ff',
				nature:'thundermm',
			}],
			['承',{
				color:'#c3f9ff',
				nature:'thundermm',
			}],
			['用间',{
				color:'#c3f9ff',
				nature:'thundermm',
			}],
			['战役篇',{
				color:'#c3f9ff',
				nature:'thundermm',
				showName:'战',
			}],
			['武将传',{
				color:'#c3f9ff',
				nature:'thundermm',
				showName:'传',
			}],
			['将',{
				nature:'firemm',
			}],
			['新杀',{
				color:'#fefedc',
				nature:'metalmm',
				showName:'新',
			}],
			['旧',{
				color:'#a4a4a4',
				nature:'black',
			}],
			['旧界',{
				color:'#a4a4a4',
				nature:'black',
			}],
			['节钺',{
				color:'#a4a4a4',
				nature:'black',
			}],
			['毅重',{
				color:'#a4a4a4',
				nature:'black',
			}],
			['★SP',{
				showName:'★',
			}],
			['K系列',{
				showName:'K',
			}],
			['经典',{
				showName:'典',
			}],
			['君',{
				color:'#fefedc',
				nature:'shenmm',
			}],
			['骰子',{
				getSpan:()=>{
					return `<span style="font-family:NonameSuits">🎲</span>`;
				}
			}],
			['SP',{
				getSpan:(prefix,name)=>{
					return `<span style="writing-mode:horizontal-tb;-webkit-writing-mode:horizontal-tb;font-family:MotoyaLMaru;transform:scaleY(0.85)">SP</span>`;
				},
			}],
			['OL',{
				getSpan:(prefix,name)=>{
					return `<span style="writing-mode:horizontal-tb;-webkit-writing-mode:horizontal-tb;font-family:MotoyaLMaru;transform:scaleY(0.85)">OL</span>`;
				},
			}],
			['RE',{
				getSpan:(prefix,name)=>{
					return `<span style="writing-mode:horizontal-tb;-webkit-writing-mode:horizontal-tb;font-family:MotoyaLMaru;transform:scaleY(0.85)">RE</span>`;
				},
			}],
			['手杀',{
				getSpan:(prefix,name)=>{
					const simple=(lib.config.buttoncharacter_prefix=='simple');
					if(lib.characterPack.shiji&&name in lib.characterPack.shiji){
						for(let i in lib.characterSort.shiji){
							if(lib.characterSort.shiji[i].includes(name)){
								prefix=get.translation(i).slice(-1);
								break;
							}
						}
						if(simple) return `<span>${prefix}</span>`;
						return `<span style="color:#def7ca" data-nature="watermm">${prefix}</span>`;
					}
					if(simple) return '<span>手杀</span>';
					return `<span style="font-family:NonameSuits">📱</span>`;
				},
			}],
			['TW',{
				getSpan:(prefix,name)=>{
					return `<span style="writing-mode:horizontal-tb;-webkit-writing-mode:horizontal-tb;font-family:MotoyaLMaru;transform:scaleY(0.85)">TW</span>`;
				},
			}],
			['TW神',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('TW')}${get.prefixSpan('神')}`
				},
			}],
			['TW将',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('TW')}${get.prefixSpan('将')}`
				},
			}],
			['OL神',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('OL')}${get.prefixSpan('神')}`
				},
			}],
			['旧神',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('旧')}${get.prefixSpan('神')}`
				},
			}],
			['旧晋',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('旧')}${get.prefixSpan('晋')}`
				},
			}],
			['新杀SP',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('新杀')}${get.prefixSpan('SP')}`
				},
			}],
			['界SP',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('界')}${get.prefixSpan('SP')}`
				},
			}],
			['S特神',{
				getSpan:(prefix,name)=>{
					return `${get.prefixSpan('★')}${get.prefixSpan('神')}`
				},
			}],
		]),
		groupnature:{
			shen:'shen',
			wei:'water',
			shu:'soil',
			wu:'wood',
			qun:'qun',
			western:'thunder',
			key:'key',
			jin:'thunder',
			ye:'thunder',
		},
		lineColor:new Map([
			['fire',[255,146,68]],
			['yellow',[255,255,122]],
			['blue',[150,202,255]],
			['green',[141,255,216]],
			['ice',[59,98,115]],
			['thunder',[141,216,255]],
			['kami',[90,118,99]],
			['white',[255,255,255]],
			['poison',[104,221,127]],
			['brown',[195,161,223]],
			['legend',[233,131,255]]
		]),
		phaseName:['phaseZhunbei','phaseJudge','phaseDraw','phaseUse','phaseDiscard','phaseJieshu'],
		quickVoice:[
			'我从未见过如此厚颜无耻之人!',
			'这波不亏',
			'请收下我的膝盖',
			'你咋不上天呢',
			'放开我的队友,冲我来',
			'你随便杀,闪不了算我输',
			'见证奇迹的时刻到了',
			'能不能快一点啊,兵贵神速啊',
			'主公,别开枪,自己人',
			'小内再不跳,后面还怎么玩儿啊',
			'你们忍心,就这么让我酱油了?',
			'我,我惹你们了吗',
			'姑娘,你真是条汉子',
			'三十六计,走为上,容我去去便回',
			'人心散了,队伍不好带啊',
			'昏君,昏君啊!',
			'风吹鸡蛋壳,牌去人安乐',
			'小内啊,您老悠着点儿',
			'不好意思,刚才卡了',
			'你可以打得再烂一点吗',
			'哥们,给力点儿行嘛',
			'哥哥,交个朋友吧',
			'妹子,交个朋友吧',
		],
		other:{
			ignore:()=>void 0
		}
	};
	const game={
		//添加新的属性杀
		addNature:(nature,translation,config)=>{
			if(!nature) throw new TypeError();
			if(translation&&translation.length) lib.translate['nature_'+nature]=translation;
			game.callHook("addNature",[nature,translation,config]);
			return nature;
		},
		//判断卡牌信息/事件是否有某个属性
		hasNature:(item,nature,player)=>{
			var natures=get.natureList(item,player);
			if(!nature) return natures.length>0;
			if(nature=='linked') return natures.some(n=>lib.linked.includes(n));
			return get.is.sameNature(natures,nature);
		},
		//设置卡牌信息/事件的属性
		setNature:(item,nature,addNature)=>{
			if(!nature) nature=[];
			if(!addNature){
				item.nature=get.nature(nature);
				if(!item.nature.length) delete item.nature;
			}
			else{
				let natures=Array.isArray(nature)?nature:nature.split(lib.natureSeparator);
				let _nature=get.natureList(item,false);
				_nature.addArray(natures);
				item.nature=_nature.join(lib.natureSeparator);
			}
			return item.nature;
		},
		//洗牌
		washCard:()=>{
			if(!ui.cardPile.hasChildNodes()&&!ui.discardPile.hasChildNodes()) return false;
			if(_status.maxShuffle!=undefined){
				if(_status.maxShuffle==0){
					if(_status.maxShuffleCheck){
						game.over(_status.maxShuffleCheck());
					}
					else{
						game.over('平局');
					}
					return [];
				}
				_status.maxShuffle--;
			}
			game.shuffleNumber++;
			const cards=Array.from(ui.cardPile.childNodes);
			if(_status.discarded){
				_status.discarded.length=0;
			}
			for(let i=0;i<ui.discardPile.childNodes.length;i++){
				var currentcard=ui.discardPile.childNodes[i];
				currentcard.vanishtag.length=0;
				if(get.info(currentcard).vanish||currentcard.storage.vanish){
					currentcard.remove();
					continue;
				}
				cards.push(currentcard);
			}
			cards.randomSort();
			return game.cardsGotoPile(cards,'triggeronly','washCard',['shuffleNumber',game.shuffleNumber])
		},
		//addGroup
		//基于钩子的添加势力方法
		addGroup:(id,short,name,config)=>{
			if(!id) throw new TypeError();
			if(lib.comparator.typeEquals(short,"object")){
				config=short;
				short=null;
			}
			if(lib.comparator.typeEquals(name,"object")){
				config=name;
				name=null;
			}
			if(!lib.comparator.typeEquals(short,"string")&&short){
				name=short;
			}
			lib.group.add(id);
			if(short)lib.translate[id] = short;
			if(name)lib.translate[`${id}2`] = name;
			game.callHook("addGroup",[id,short,name,config]);
			return id;
		},
		//通用的调用钩子函数
		callHook:(name,args)=>{
			const callHook=()=>{
				for(const hook of lib.hooks[name]){
					if(hook!=null&&typeof hook=="function"){
						hook(...args);
					}
				}
			}
			if ("onload" in lib) lib.onload.add(callHook);
			else callHook();
		},
		//Yingbian
		//应变
		yingbianEffect:function(event,content){
			const yingbianEffect=game.createEvent('yingbianEffect');
			yingbianEffect.player=event.player;
			yingbianEffect.card=event.card;
			yingbianEffect._trigger=event;
			yingbianEffect.setContent(content);
			yingbianEffect._args=Array.from(arguments);
			return yingbianEffect;
		},
		setYingbianConditionColor:(yingbianCondition,color)=>game.broadcastAll((yingbianCondition,color)=>lib.yingbian.condition.color.set(yingbianCondition,color),yingbianCondition,color),
		setComplexYingbianCondition:(yingbianCondition,condition)=>game.broadcastAll((yingbianCondition,condition)=>lib.yingbian.condition.complex.set(yingbianCondition,condition),yingbianCondition,condition),
		setSimpleYingbianCondition:(yingbianCondition,condition)=>game.broadcastAll((yingbianCondition,condition)=>lib.yingbian.condition.simple.set(yingbianCondition,condition),yingbianCondition,condition),
		setYingbianEffect:(yingbianEffect,effect)=>game.broadcastAll((yingbianEffect,effect)=>lib.yingbian.effect.set(yingbianEffect,effect),yingbianEffect,effect),
		setYingbianPrompt:(yingbian,prompt)=>game.broadcastAll((yingbian,prompt)=>lib.yingbian.prompt.set(yingbian,prompt),yingbian,prompt),
		//动态CSS from libnodiz
		dynamicStyle:{
			init:()=>{
				const that=game.dynamicStyle;
				that._cache={};
				that._cache.rules=[];
				that._cache.style=document.createElement("style");
				that._cache.style.id="game.dynamicStyle";
				document.head.appendChild(that._cache.style);
				that._cache.sheet = that._cache.style.sheet;
				delete game.dynamicStyle.init;
				return true;
			},
			translate:style=>{
				let result=[];
				for(const name in style){
					result.push(`${name.replace(/([A-Z])/g, match => `-${match.toLowerCase()}`)}: ${style[name]};`);
				}
				return result.join(" ");
			},
			generate:(name, style)=>[`${name} {`, game.dynamicStyle.translate(style), "}"].join(" "),
			has:name=>game.dynamicStyle._cache.rules.some(item=>item[0]==name),
			get:name=>game.dynamicStyle.find(item=>item[0]==name)[1],
			find:fn=>game.dynamicStyle._cache.rules.find(fn),
			size:()=>game.dynamicStyle._cache.rules.length,
			indexOf:name=>{
				for (let i=0;i<game.dynamicStyle._cache.rules.length;++i){
					if(name==game.dynamicStyle._cache.rules[i][0]) return i;
				}
				return -1;
			},
			add:(name,style)=>{
				const that=game.dynamicStyle;
				return that.update(name,that.has(name)?Object.assign({},that.get(name),style):style);
			},
			addObject:object=>{
				const that=game.dynamicStyle;
				let result=[];
				for(const name in object){
					result.push(that.add(name, object[name]));
				}
				return result;
			},
			remove:name=>{
				const that=game.dynamicStyle;
				if(!that.has(name)) return false;
				const index=that.indexOf(name);
				that._cache.rules.splice(index,1);
				that._cache.sheet.deleteRule(index);
				return true;
			},
			update:(name,style)=>{
				const that=game.dynamicStyle;
				try{
					if(that.has(name)){
						const index=that.indexOf(name);
						that._cache.sheet.deleteRule(index);
						that._cache.sheet.insertRule(that.generate(name,style),index);
						that._cache.rules[index] = [name, style];
					}else{
						const index=that._cache.rules.length;
						that._cache.rules.push([name,style]);
						that._cache.sheet.insertRule(that.generate(name,style),index);
					}
					return true;
				}
				catch(e){
					console.log(e);
					return false;
				}
			}
		},
		//Add a background music to the config option
		//在设置选项中添加一首背景音乐
		addBackgroundMusic:(link,musicName,aozhan)=>{
			const backgroundMusicSetting=ui[aozhan?'aozhan_bgm':'background_music_setting'],menu=backgroundMusicSetting._link.menu,config=backgroundMusicSetting._link.config;
			if(typeof musicName!='string') musicName=link;
			if(aozhan) lib.mode.guozhan.config.aozhan_bgm.item[link]=musicName;
			else lib.config.all.background_music.add(link);
			config.item[link]=musicName;
			const textMenu=ui.create.div('',musicName,menu,function(){
				const node=this.parentNode._link,config=node._link.config;
				node._link.current=this.link;
				const tmpName=node.lastChild.innerHTML;
				node.lastChild.innerHTML=config.item[this._link];
				if(config.onclick&&config.onclick.call(node,this._link,this)===false) node.lastChild.innerHTML=tmpName;
				if(config.update) config.update();
			},menu.childElementCount-2);
			textMenu._link=link;
			config.updatex.call(backgroundMusicSetting,[]);
		},
		//Remove a background music from the config option
		//从设置选项中移除一首背景音乐
		removeBackgroundMusic:(link,aozhan)=>{
			if(aozhan){
				if(['disabled','random'].includes(link)) return;
				delete lib.mode.guozhan.config.aozhan_bgm.item[link];
				if(!Array.isArray(_status.aozhanBGMToRemove)) _status.aozhanBGMToRemove=[];
				_status.aozhanBGMToRemove.add(link);
			}
			else{
				if(['music_off','music_custom','music_random'].includes(link)) return;
				lib.config.all.background_music.remove(link);
			}
			const backgroundMusicSetting=ui[aozhan?'aozhan_bgm':'background_music_setting'],config=backgroundMusicSetting._link.config;
			config.updatex.call(backgroundMusicSetting,[]);
		},
		updateBackground:()=>{
			const background=_status.tempBackground||lib.config.image_background;
			ui.background.delete();
			const uiBackground=ui.background=ui.create.div('.background'),style=uiBackground.style;
			if(lib.config.image_background_blur){
				style.filter='blur(8px)';
				style.webkitFilter='blur(8px)';
				style.transform='scale(1.05)';
			}
			document.body.insertBefore(uiBackground,document.body.firstChild);
			if(background.startsWith('db:')) uiBackground.setBackgroundDB(background.slice(3));
			else if(background.startsWith('ext:')) uiBackground.setBackgroundImage(`extension/${background.slice(4)}`);
			else if(background=='default'){
				uiBackground.animate('start');
				style.backgroundImage='none';
			}
			else if(background.startsWith('custom_')){
				style.backgroundImage='none';
				game.getDB('image',background).then(fileToLoad=>{
					if(!fileToLoad) return;
					const fileReader = new FileReader();
					fileReader.onload=fileLoadedEvent=>style.backgroundImage=`url(${fileLoadedEvent.target.result})`;
					fileReader.readAsDataURL(fileToLoad, "UTF-8");
				});
			}
			else uiBackground.setBackgroundImage(`image/background/${background}.jpg`);
			style.backgroundSize='cover';
			style.backgroundPosition='50% 50%';
		},
		//Generate a beatmap using the given BPM, beats, and offset
		//用给定的BPM、节拍和偏移生成谱面
		generateBeatmapTimeleap:(bpm,beats,offset)=>beats.map(value=>Math.round(value*60000/bpm+(offset||0))),
		updateRenku:function(){
			game.broadcast(function(renku){
				_status.renku=renku;
			},_status.renku);
			for(var i of game.players){
				if(i.storage.renku) i.markSkill('renku');
			}
		},
		loseAsync:function(arg){
			var next=game.createEvent('loseAsync');
			next.forceDie=true;
			next.getd=function(player,key,position){
				if(!position) position=ui.discardPile;
				if(!key) key='cards';
				var cards=[],event=this;
				game.checkGlobalHistory('cardMove',function(evt){
					if(evt.name!='lose'||evt.position!=position||evt.getParent()!=event) return;
					if(player&&player!=evt.player) return;
					cards.addArray(evt[key]);
				});
				return cards;
			};
			next.getl=function(player){
				const that=this;
				const map={
					player:player,
					hs:[],
					es:[],
					js:[],
					ss:[],
					xs:[],
					cards:[],
					cards2:[],
					gaintag_map:{},
				};
				player.checkHistory('lose',function(evt){
					if(evt.parent==that){
						map.hs.addArray(evt.hs);
						map.es.addArray(evt.es);
						map.js.addArray(evt.js);
						map.ss.addArray(evt.ss);
						map.xs.addArray(evt.xs);
						map.cards.addArray(evt.cards);
						map.cards2.addArray(evt.cards2);
						for(let key in evt.gaintag_map){
							if(!map.gaintag_map[key]) map.gaintag_map[key]=[];
							map.gaintag_map[key].addArray(evt.gaintag_map[key]);
						}
					}
				});
				return map;
			};
			next.getg=function(player){
				var that=this;
				var cards=[];
				player.checkHistory('gain',function(evt){
					if(evt.parent==that){
						cards.addArray(evt.cards);
					}
				});
				return cards;
			};
			if(arg&&get.is.object(arg)){
				for(var i in arg) next[i]=arg[i];
			}
			return next;
		},
		callFuncUseStepCache:function(prefix,func,params){
			if(typeof func != 'function')return;
			if(_status.closeStepCache || !_status.event)return func.apply(null,params);
			var cacheKey = "["+prefix+"]"+get.paramToCacheKey.apply(null,params);
			var ret = _status.event.getStepCache(cacheKey);
			if(ret === undefined || ret === null){
				ret = func.apply(null,params);
				_status.event.putStepCache(cacheKey,ret);
			}
			return ret;
		},
		getRarity:function(name){
			var rank=lib.rank.rarity;
			if(rank.legend.contains(name)) return 'legend';
			if(rank.epic.contains(name)) return 'epic';
			if(rank.rare.contains(name)) return 'rare';
			if(get.mode()!='chess'&&rank.junk.contains(name)) return 'junk';
			return 'common';
		},
		hasGlobalHistory:function(key,filter,last){
			if(!key) return _status.globalHistory[_status.globalHistory.length-1];
			if(!filter) return _status.globalHistory[_status.globalHistory.length-1][key];
			else{
				const history=game.getGlobalHistory(key);
				if(last){
					const lastIndex=history.indexOf(last);
					return history.some((event,index)=>{
						if(index>lastIndex) return false;
						return filter(event);
					});
				}
				else{
					return history.some(filter);
				}
			}
		},
		checkGlobalHistory:function(key,filter,last){
			if(!key) return _status.globalHistory[_status.globalHistory.length-1];
			if(!filter) return _status.globalHistory[_status.globalHistory.length-1][key];
			else{
				const history=game.getGlobalHistory(key);
				if(last){
					const lastIndex=history.indexOf(last);
					history.forEach((event,index)=>{
						if(index>lastIndex) return false;
						return filter(event);
					});
				}
				else{
					history.forEach(filter);
				}
			}
		},
		getGlobalHistory:function(key,filter,last){
			if(!key) return _status.globalHistory[_status.globalHistory.length-1];
			if(!filter) return _status.globalHistory[_status.globalHistory.length-1][key];
			else{
				const history=game.getGlobalHistory(key);
				if(last){
					const lastIndex=history.indexOf(last);
					return history.filter((event,index)=>{
						if(index>lastIndex) return false;
						return filter(event);
					})
				}
				return history.filter(filter);
			}
		},
		hasAllGlobalHistory:function(key,filter,last){
			if(!key||!filter) return;
			const stopped=false;
			_status.globalHistory.forEach(value=>{
				if(value[key]){
					if(last&&value[key].includes(last)&&!stopped){
						stopped=true;
						const lastIndex=value[key].indexOf(last);
						if(value[key].some((event,index)=>{
							if(index>lastIndex) return false;
							return filter(event);
						})) return true;
					}
					else{
						if(value[key].some(filter)) return true;
					}
				}
			})
		},
		checkAllGlobalHistory:function(key,filter,last){
			if(!key||!filter) return;
			const stopped=false;
			_status.globalHistory.forEach(value=>{
				if(value[key]){
					if(last&&value[key].includes(last)&&!stopped){
						stopped=true;
						const lastIndex=value[key].indexOf(last);
						value[key].forEach((event,index)=>{
							if(index>lastIndex) return false;
							return filter(event);
						});
					}
					else{
						value[key].forEach(filter);
					}
				}
			})
		},
		getAllGlobalHistory:function(key,filter,last){
			const history=[];
			_status.globalHistory.forEach(value=>{
				if(!key||!value[key]){
					history.push(value);
				}
				else{
					history.push(...value[key]);
				}
			})
			if(filter){
				if(last){
					const lastIndex=history.indexOf(last);
					return history.filter(function(event,index){
						if(index>lastIndex) return false;
						return filter(event);
					});
				}
				return history.filter(filter);
			}
			return history;
		},
		cardsDiscard:function(cards){
			var type=get.itemtype(cards);
			if(type!='cards'&&type!='card') return;
			var next=game.createEvent('cardsDiscard');
			next.cards=type=='cards'?cards.slice(0):[cards];
			next.setContent('cardsDiscard');
			next.getd=function(player,key,position){
				return this.cards.slice(0);
			};
			return next;
		},
		cardsGotoOrdering:function(cards){
			var type=get.itemtype(cards);
			if(type!='cards'&&type!='card') return;
			var next=game.createEvent('cardsGotoOrdering');
			next.cards=type=='cards'?cards.slice(0):[cards];
			next.setContent('cardsGotoOrdering');
			return next;
		},
		cardsGotoSpecial:function(cards,bool){
			var type=get.itemtype(cards);
			if(type!='cards'&&type!='card') return;
			var next=game.createEvent('cardsGotoSpecial');
			next.cards=type=='cards'?cards.slice(0):[cards];
			if(bool=='toRenku') next.toRenku=true;
			else if(bool===false) next.notrigger=true;
			next.setContent('cardsGotoSpecial');
			return next;
		},
		cardsGotoPile:function(){
			const cards=[];
			const next=game.createEvent('cardsGotoPile');
			next.cards=cards;
			for(let i=0;i<arguments.length;i++){
				let arg=arguments[i],itemtype=get.itemtype(arg);
				if(itemtype=='cards'){
					cards.addArray(arg);
				}
				else if(itemtype=='card'){
					cards.add(arg);
				}
				else if(typeof arg=='function'){
					next.insert_index=arg;
				}
				else if(typeof arg=='string'){
					if(arg=='insert') next.insert_card=true;
					else if(arg=='washCard') next.washCard=true;
					else if(arg=='triggeronly') next._triggeronly=true;
				}
				else if(Array.isArray(arg)&&arg.length==2&&typeof arg[0]=='string'){
					next.set(arg[0],arg[1]);
				}
			}
			if(!cards.length){
				_status.event.next.remove(next);
			}
			else{
				next.setContent('cardsGotoPile');
				if(next._triggeronly) game.$cardsGotoPile(next);
			}
			return next;
		},
		$cardsGotoPile:function(event){
			const cards=event.cards;
			const pile=ui.cardPile;
			for(let i=0;i<cards.length;i++){
				if(event.insert_index){
					cards[i].fix();
					pile.insertBefore(cards[i],event.insert_index(event,cards[i]));
				}
				else if(event.insert_card){
					cards[i].fix();
					pile.insertBefore(cards[i],pile.firstChild);
				}
				else{
					cards[i].fix();
					pile.appendChild(cards[i]);
				}
			}
			game.updateRoundNumber();
		},
		online:false,
		onlineID:null,
		onlineKey:null,
		showHistory:function(pause){
			if(lib.config.show_history=='left'){
				ui.window.classList.add('leftbar');
			}
			else if(lib.config.show_history=='right'){
				ui.window.classList.add('rightbar');
			}
			if(pause!=false&&ui.pause){
				ui.pause.show();
			}
		},
		createBackground:function(src,blur){
			var current=document.body.querySelector('.background.upper');
			if(current){
				current.delete();
			}
			var node=ui.create.div('.background.blurbg',document.body);
			node.setBackgroundImage(src);
			node.style.backgroundSize='cover';
			if(blur){
				node.classList.add('paused')
			}
			return node;
		},
		changeLand:(url,player)=>{
			game.addVideo('changeLand',player,url);
			const parsedPath=lib.path.parse(url);
			delete parsedPath.base;
			if(!parsedPath.dir) parsedPath.dir='image/card/';
			if(!parsedPath.ext) parsedPath.ext='.jpg';
			game.broadcastAll((formattedPath,name,skill,player)=>{
				const node=ui.create.div('.background.upper.land');
				node.setBackgroundImage(formattedPath);
				node.destroy=()=>{
					if (node.skill) {
						game.removeGlobalSkill(node.skill);
						if(node.system) node.system.remove();
					}
					node.classList.add('hidden');
					setTimeout(()=>node.remove(),3000);
					if(ui.land==node) ui.land=null;
				}
				if(ui.land){
					document.body.insertBefore(node,ui.land);
					ui.land.destroy();
				}
				else{
					node.classList.add('hidden');
					document.body.insertBefore(node,ui.window);
					ui.refresh(node);
					node.classList.remove('hidden');
				}
				ui.land=node;
				if(!name) return;
				node.name=name;
				node.skill=skill;
				if(player){
					node.player=player;
					player.addTempSkill('land_used');
				}
				lib.setPopped(node.system=ui.create.system(lib.translate[skill],null,true,true),()=>{
					const uiIntro=ui.create.dialog('hidden');
					uiIntro.addText(player?`来源:${get.translation(player)}`:'地图').style.margin='0';
					uiIntro._place_text=uiIntro.add(ui.create.div('.text',lib.translate[`${skill}_info`]));
					uiIntro.add(ui.create.div('.placeholder.slim'));
					return uiIntro;
				},200);
				game.addGlobalSkill(skill);
			},lib.path.format(parsedPath),parsedPath.name,`${name}_skill`,player);
		},
		checkFileList:function(updates,proceed){
			var n=updates.length;
			if(!n){
				proceed(n);
			}
			for(var i=0;i<updates.length;i++){
				if(lib.node&&lib.node.fs){
					lib.node.fs.access(__dirname+'/'+updates[i],(function(entry){
						return function(err){
							if(!err){
								var stat=lib.node.fs.statSync(__dirname+'/'+entry);
								if(stat.size==0){
									err=true;
								}
							}
							if(err){
								n--;
								if(n==0){
									proceed();
								}
							}
							else{
								n--;
								updates.remove(entry);
								if(n==0){
									proceed();
								}
							}
						}
					}(updates[i])));
				}
				else{
					resolveLocalFileSystemURL(lib.assetURL+updates[i],(function(name){
						return function(entry){
							n--;
							updates.remove(name);
							if(n==0){
								proceed();
							}
						}
					}(updates[i])),function(){
						n--;
						if(n==0){
							proceed();
						}
					});
				}
			}
		},
		replaceHandcards:function(){
			var next=game.createEvent('replaceHandcards');
			if(Array.isArray(arguments[0])){
				next.players=arguments[0];
			}
			else{
				next.players=[];
				for(var i=0;i<arguments.length;i++){
					if(get.itemtype(arguments[i])=='player'){
						next.players.push(arguments[i]);
					}
				}
			}
			if(_status.connectMode){
				next.setContent('replaceHandcardsOL');
			}
			else{
				next.setContent('replaceHandcards');
			}
		},
		removeCard:function(name){
			for(var i=0;i<lib.card.list.length;i++){
				if(lib.card.list[i][2]==name){
					lib.card.list.splice(i--,1);
				}
			}
			var list=[];
			for(var i=0;i<ui.cardPile.childElementCount;i++){
				if(ui.cardPile.childNodes[i].name==name){
					list.push(ui.cardPile.childNodes[i]);
				}
			}
			for(var i=0;i<list.length;i++){
				list[i].remove();
			}
		},
		randomMapOL:function(type){
			if(type=='hidden'){
				ui.arena.classList.add('playerhidden');
			}
			game.prepareArena();
			if(window.isNonameServer){
				game.me=ui.create.player();
			}
			var list=[];
			for(var i=0;i<game.players.length;i++){
				if(game.players[i]!=game.me){
					list.push(game.players[i]);
				}
			}
			var map=[];
			for(var i=0;i<lib.node.clients.length;i++){
				if(!list.length) break;
				var current=list.randomRemove();
				current.ws=lib.node.clients[i];
				current.playerid=current.ws.id;
				current.nickname=current.ws.nickname;
				current.setNickname();
			}
			if(!window.isNonameServer){
				game.me.playerid=get.id();
				game.me.nickname=get.connectNickname();
				game.me.setNickname();
			}
			for(var i=0;i<game.players.length;i++){
				if(!game.players[i].playerid){
					game.players[i].playerid=get.id();
				}
				map.push([game.players[i].playerid,game.players[i].nickname]);
				lib.playerOL[game.players[i].playerid]=game.players[i];
			}
			game.broadcast(function(map,config,hidden){
				if(hidden){
					ui.arena.classList.add('playerhidden');
				}
				lib.configOL=config;
				ui.create.players();
				ui.create.me();
				game.me.playerid=game.onlineID;
				game.me.nickname=get.connectNickname();
				for(var i=0;i<map.length;i++){
					if(map[i][0]==game.me.playerid){
						map=map.concat(map.splice(0,i));
						break;
					}
				}
				for(var i=0;i<game.players.length;i++){
					game.players[i].playerid=map[i][0];
					game.players[i].nickname=map[i][1];
					game.players[i].setNickname();
					lib.playerOL[game.players[i].playerid]=game.players[i];
				}
				_status.mode=lib.configOL[lib.configOL.mode+'_mode'];
			},map,lib.configOL,type=='hidden');
			_status.mode=lib.configOL[lib.configOL.mode+'_mode'];
			game.chooseCharacterOL();
		},
		closeMenu:function(){
			if(ui.menuContainer&&!ui.menuContainer.classList.contains('hidden')){
				ui.click.configMenu();
			}
		},
		closeConnectMenu:function(){
			if(ui.connectMenuContainer&&!ui.connectMenuContainer.classList.contains('hidden')){
				ui.click.connectMenu();
			}
		},
		closePopped:function(){
			if(ui.currentpopped){
				if(ui.currentpopped._uiintro){
					ui.currentpopped._uiintro.delete();
					delete ui.currentpopped._uiintro;
				}
				delete ui.currentpopped;
			}
		},
		broadcast:function(){
			if(!lib.node||!lib.node.clients||game.online) return;
			for(var i=0;i<lib.node.clients.length;i++){
				if(lib.node.clients[i].inited){
					lib.node.clients[i].send.apply(lib.node.clients[i],arguments);
				}
			}
		},
		broadcastAll:function(){
			if(game.online) return;
			var argc=arguments.length;
			var args=new Array(argc);
			for(var i=0;i<argc;i++){
				args[i]=arguments[i];
			}
			game.broadcast.apply(this,args);
			var func=args.shift();
			if(typeof func=='string'){
				func=lib.message.client[func];
			}
			if(typeof func=='function'){
				func.apply(this,args);
			}
		},
		syncState:function(){
			var state=null;
			if(game.getState){
				state=game.getState();
			}
			game.broadcast(function(state,current,number){
				if(game.updateState&&state) game.updateState(state);
				_status.currentPhase=current;
				game.phaseNumber=number;
			},state,_status.currentPhase,game.phaseNumber);
		},
		updateWaiting:function(){
			var map=[];
			for(var i=0;i<game.connectPlayers.length;i++){
				var player=game.connectPlayers[i];
				if(player.playerid){
					if(!game.onlinezhu){
						game.onlinezhu=player.playerid;
						game.send('server','changeAvatar',player.nickname,player.avatar);
						_status.onlinenickname=player.nickname;
						_status.onlineavatar=player.avatar;
					}
					map[i]=[player.nickname,player.avatar,player.playerid];
					if(player.playerid==game.onlinezhu){
						map[i].push('zhu');
					}
				}
				else if(player.classList.contains('unselectable2')){
					map[i]='disabled';
				}
				else{
					map[i]=null;
				}
			}
			game.broadcast('updateWaiting',map);
		},
		waitForPlayer:function(func){
			var next=game.createEvent('waitForPlayer',false);
			next.func=func;
			next.setContent('waitForPlayer');
		},
		countDown:function(time,onEnd){
			time=parseInt(time);
			if(!time) return;
			if(time<=0) return;
			var current=time;
			ui.timer.set(current,1);
			_status.countDown=setInterval(function(){
				if(--current){
					ui.timer.set(current,current/time);
				}
				else{
					ui.timer.set(0,0);
					clearInterval(_status.countDown);
					delete _status.countDown;
					if(onEnd) onEnd();
				}
			},1000);
		},
		countChoose:function(clear){
			if(_status.imchoosing){
				return;
			}
			_status.imchoosing=true;
			if(_status.connectMode&&!_status.countDown){
				ui.timer.show();
				var num;
				//这么一大行都是为了祢衡
				if(_status.event&&_status.event.name=='chooseToUse'&&_status.event.type=='phase'&&
					_status.event.player&&_status.event.player.forceCountChoose&&
					typeof _status.event.player.forceCountChoose.phaseUse=='number'){
					num=_status.event.player.forceCountChoose.phaseUse;
				}
				else if(_status.connectMode){
					num=lib.configOL.choose_timeout;
				}
				else{
					num=get.config('choose_timeout');
				}
				game.countDown(parseInt(num),function(){
					ui.click.auto();
					ui.timer.hide();
				});
				if(!game.online&&game.me){
					if(_status.event.getParent().skillHidden){
						for(var i=0;i<game.players.length;i++){
							game.players[i].showTimer();
						}
						game.me._hide_all_timer=true;
					}
					else if(!_status.event._global_waiting){
						game.me.showTimer();
					}
				}
			}
			else if(_status.event.player.forceCountChoose&&_status.event.isMine()&&!_status.countDown){
				var info=_status.event.player.forceCountChoose;
				var num;
				if(_status.event.name=='chooseToUse'&&_status.event.type=='phase'&&typeof info.phaseUse=='number'){
					num=info.phaseUse;
				}
				else if(typeof info[_status.event.name]=='number'){
					num=info[_status.event.name]
				}
				else if(info.default){
					num=info.default;
				}
				else return;
				var finish=function(){
					if(_status.event.endButton){
						if(_status.event.skill){
							ui.click.cancel();
						}
						ui.click.cancel();
					}
					else{
						if(ui.confirm&&ui.confirm.str){
							if(ui.confirm.str.includes('c')){
								ui.click.cancel();
							}
							else if(ui.confirm.str.includes('o')){
								ui.click.ok();
							}
						}
						else if(['chooseControl','chooseBool'].contains(_status.event.name)&&_status.paused){
							_status.event.result='ai';
							game.resume();
						}
						else{
							ui.click.auto('forced');
							setTimeout(function(){
								ui.click.auto('forced');
							},200);
						}
					}
					ui.timer.hide();
				};
				if(!num){
					ui.timer.hide();
					game.uncheck();
					setTimeout(finish,200);
				}
				else{
					ui.timer.show();
					game.countDown(num,finish);
				}
			}
		},
		stopCountChoose:function(){
			if(_status.countDown){
				clearInterval(_status.countDown);
				delete _status.countDown;
				ui.timer.hide();
			}
			if(_status.connectMode&&!game.online&&game.me){
				if(game.me._hide_all_timer){
					delete game.me._hide_all_timer;
					for(var i=0;i<game.players.length;i++){
						game.players[i].hideTimer();
					}
				}
				else if(!_status.event._global_waiting){
					game.me.hideTimer();
				}
			}
		},
		connect:function(ip,callback){
			if(game.online) return;
			var withport=false;
			var index=ip.lastIndexOf(':');
			if(index!=-1){
				index=parseFloat(ip.slice(index+1));
				if(index&&Math.floor(index)==index){
					withport=true;
				}
			}
			if(!withport){
				ip=ip+':8080';
			}
			_status.connectCallback=callback;
			try{
				if(game.ws){
					game.ws._nocallback=true;
					game.ws.close();
					delete game.ws;
				}
				var str='';
				if(!ip.startsWith('wss://')&&!ip.startsWith('ws://')) str=(get.config('wss_mode','connect')?'wss://':'ws://');
				game.ws=new WebSocket(str+ip+'');
			}
			catch(e){
				alert('错误:无效联机地址');
				if(callback){
					callback(false);
				}
				return;
			}
			game.ws.onopen=lib.element.ws.onopen;
			game.ws.onmessage=lib.element.ws.onmessage;
			game.ws.onerror=lib.element.ws.onerror;
			game.ws.onclose=lib.element.ws.onclose;
			_status.ip=ip;
		},
		send:function(){
			if(game.observe&&arguments[0]!='reinited') return;
			if(game.ws){
				var args=Array.from(arguments);
				if(typeof args[0]=='function'){
					args.unshift('exec');
				}
				game.ws.send(JSON.stringify(get.stringifiedResult(args)));
			}
		},
		sendTo:function(id,message){
			var ws={wsid:id};
			for(var i in lib.element.nodews){
				ws[i]=lib.element.nodews[i];
			}
			var client={
				ws:ws,
				id:ws.wsid,
				closed:false
			};
			for(var i in lib.element.client){
				client[i]=lib.element.client[i];
			}
			client.send(message);
		},
		createServer:function(){
			lib.node.clients=[];
			lib.node.banned=[];
			lib.node.observing=[];
			lib.node.torespond={};
			lib.node.torespondtimeout={};
			lib.playerOL={};
			lib.cardOL={};
			lib.wsOL={};
			ui.create.roomInfo();
			ui.create.chat();

			if(game.onlineroom){

			}
			else{
				var WebSocketServer=require('ws').Server;
				var wss=new WebSocketServer({port:8080});

				game.ip=get.ip();

				wss.on('connection',lib.init.connection);
			}
		},
		playAudio:function(){
			if(_status.video&&arguments[1]!='video') return;
			let path='',emptyPath=true,notCheckDBPath=true,onError=null;
			for(const argument of arguments){
				if(typeof argument==='string'||typeof argument=='number'){
					if(emptyPath) emptyPath=false;
					else if(notCheckDBPath){
						notCheckDBPath=false;
						if(/^db:extension-[^:]*$/.test(path)) path+=':';
						else path+='/';
					}
					else path+='/';
					path+=argument;
				}
				else if(typeof argument=='function') onError=argument;
				if(_status.video) break;
			}
			if(path.startsWith('ext:')) path=path.replace(/^ext:/,'extension/');
			else if(!path.startsWith('db:')) path=`audio/${path}`;
			if(!lib.config.repeat_audio&&_status.skillaudio.contains(path)) return;
			_status.skillaudio.add(path);
			game.addVideo('playAudio',null,path);
			setTimeout(()=>_status.skillaudio.remove(path),1000);
			const audio=document.createElement('audio');
			audio.autoplay=true;
			audio.volume=lib.config.volumn_audio/8;
			audio.addEventListener('ended',()=>audio.remove());
			audio.onerror=event=>{
				audio.remove();
				if(onError) onError(event);
			};
			//Some browsers do not support "autoplay", so "oncanplay" listening has been added
			audio.oncanplay=()=>Promise.resolve(audio.play()).catch(()=>void 0);
			new Promise((resolve,reject)=>{
				if(path.startsWith('db:')) game.getDB('image',path.slice(3)).then(octetStream=>resolve(get.objectURL(octetStream)),reject);
				else if(lib.path.extname(path)) resolve(`${lib.assetURL}${path}`);
				else resolve(`${lib.assetURL}${path}.mp3`);
			}).then(resolvedPath=>{
				audio.src=resolvedPath;
				ui.window.appendChild(audio);
			});
			return audio;
		},
		trySkillAudio:function(skill,player,directaudio){
			game.broadcast(game.trySkillAudio,skill,player,directaudio);
			var info=get.info(skill);
			if(!info) return;
			if(!lib.config.background_speak) return;
			if(typeof player=='string') player={name:player};
			else{
				if(info.direct&&!directaudio) return;
				if(lib.skill.global.includes(skill)&&!lib.skill[skill].forceaudio) return;
			}
			var audioName=skill;
			var audioInfo=info.audio;
			var fixedNum;
			if(info.audioname2){
				if(info.audioname2[player.name]){
					audioName+='_'+player.name;
					audioInfo=info.audioname2[player.name];
				}
				else if(info.audioname2[player.name1]){
					audioName+='_'+player.name1;
					audioInfo=info.audioname2[player.name1];
				}
				else if(info.audioname2[player.name2]){
					audioName+='_'+player.name2;
					audioInfo=info.audioname2[player.name2];
				}
			}
			var history=[];
			while(true){//可以嵌套引用了
				if(history.includes(audioName)) break;
				history.push(audioName);
				if(typeof audioInfo=='string'&&lib.skill[audioInfo]){
					audioName=audioInfo;
					audioInfo=lib.skill[audioName].audio;
					continue;
				}
				if(Array.isArray(audioInfo)){
					audioName=audioInfo[0];
					if(!fixedNum) fixedNum=audioInfo[1];//数组会取第一个指定语音数
					// TODO: 判断不完整,但现在无合适的方法,先放着 @kuangshen04
					if(audioName in lib.skill) audioInfo=lib.skill[audioName].audio;
					else audioInfo=parseInt(fixedNum);
					continue;
				}
				break;
			}
			if(Array.isArray(info.audioname)&&player){
				if(info.audioname.includes(player.name)&&(!info.audioname2||!info.audioname2[player.name])) audioName+='_'+player.name;
				else if(info.audioname.includes(player.name1)&&(!info.audioname2||!info.audioname2[player.name1])) audioName+='_'+player.name1;
				else if(info.audioname.includes(player.name2)&&(!info.audioname2||!info.audioname2[player.name2])) audioName+='_'+player.name2;
			}
			if(typeof audioInfo=='string'){
				if(audioInfo.startsWith('db:')){
					audioInfo=audioInfo.split(':');
					if(audioInfo.length<4) return;
					if(audioInfo[3]=='true') game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${audioName}.${audioInfo[4]||'mp3'}`);
					else{
						audioInfo[3]=fixedNum?Math.min(parseInt(audioInfo[3]),fixedNum):parseInt(audioInfo[3]);
						if(!audioInfo[3]) return;
						game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${audioName}${Math.floor(audioInfo[3]*Math.random())+1}.${audioInfo[4]||'mp3'}`);
					}
				}
				else if(audioInfo.startsWith('ext:')){
					audioInfo=audioInfo.split(':');
					if(audioInfo.length<3) return;
					if(audioInfo[2]=='true') game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${audioName}.${audioInfo[3]||'mp3'}`);
					else{
						audioInfo[2]=fixedNum?Math.min(parseInt(audioInfo[2]),fixedNum):parseInt(audioInfo[2]);
						if(!audioInfo[2]) return;
						game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${audioName}${Math.floor(audioInfo[2]*Math.random())+1}.${audioInfo[3]||'mp3'}`);
					}
				}
			}
			else if(typeof audioInfo=='number'){
				if(fixedNum) audioInfo=Math.min(audioInfo, fixedNum);
				game.playAudio('skill',`${audioName}${Math.floor(audioInfo*Math.random())+1}`);
			}
			//直接指定配音文件名的新格式
			else if(typeof audioInfo=="object"){
				if(!("type" in audioInfo&&audioInfo.type=="direct"&&"files" in audioInfo)) return;
				let audioFiles=audioInfo.files;
				if(typeof audioFiles!="object") return;
				if(!Array.isArray(audioFiles)){
					if(!player) return;
					if(player.name&&player.name in audioFiles&&(!info.audioname2||!info.audioname2[player.name]))audioFiles=audioFiles[player.name];
					else if(player.name1&&player.name1 in audioFiles&&(!info.audioname2||!info.audioname2[player.name1]))audioFiles=audioFiles[player.name1];
					else if(player.name2&&player.name2 in audioFiles&&(!info.audioname2||!info.audioname2[player.name2]))audioFiles=audioFiles[player.name2];
				}
				if(!Array.isArray(audioFiles)) return;
				let length=audioFiles.length;
				if(fixedNum)length=Math.min(length,fixedNum);
				//game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${audioName}${+1}.${audioInfo[3]||'mp3'}`);
				game.playAudio(audioFiles[Math.floor(length*Math.random())]);
			}
			else if(audioInfo) game.playAudio('skill',audioName);
			else if(info.audio!==false) game.playSkillAudio(audioName);
		},
		playSkillAudio:function(name,index){
			if(_status.video&&arguments[1]!='video') return;
			if(!lib.config.repeat_audio&&_status.skillaudio.includes(name)) return;
			game.addVideo('playSkillAudio',null,name);
			if(name.indexOf('|')<name.lastIndexOf('|')){
				name=name.slice(name.lastIndexOf('|')+1);
			}
			_status.skillaudio.add(name);
			setTimeout(function(){
				_status.skillaudio.remove(name);
			},1000);
			var str='audio/skill/';
			var audio=document.createElement('audio');
			audio.autoplay=true;
			audio.volume=lib.config.volumn_audio/8;
			audio.src=lib.assetURL+str+name+'.mp3';
			audio.addEventListener('ended',function(){
				this.remove();
			});
			if(typeof index!='number'){
				index=Math.ceil(Math.random()*2);
			}
			audio._changed=1;
			audio.onerror=function(){
				switch(this._changed){
					case 1:{
						audio.src=lib.assetURL+str+name+'.ogg';
						this._changed=2;
						break;
					}
					case 2:{
						audio.src=lib.assetURL+str+name+index+'.mp3';
						this._changed=3;
						break;
					}
					case 3:{
						audio.src=lib.assetURL+str+name+index+'.ogg';
						this._changed=4;
						break;
					}
					default:{
						this.remove();
					}
				}
			};
			//Some browsers do not support "autoplay", so "oncanplay" listening has been added
			audio.oncanplay=function(){
				Promise.resolve(this.play()).catch(()=>void 0);
			};
			ui.window.appendChild(audio);
		},
		playBackgroundMusic:()=>{
			if(lib.config.background_music=='music_off'){
				ui.backgroundMusic.src='';
				return;
			}
			if(_status._aozhan){
				const aozhanBGMConfiguration=lib.config.mode_config.guozhan.aozhan_bgm;
				if(aozhanBGMConfiguration=='disabled') return;
				let aozhan=_status.tempAozhan||aozhanBGMConfiguration;
				if(Array.isArray(aozhan)) aozhan=aozhan.randomGet('disabled',_status.currentAozhan)||aozhanBGMConfiguration;
				if(aozhan=='random') aozhan=Object.keys(lib.mode.guozhan.config.aozhan_bgm.item).randomGet('disabled','random',_status.currentAozhan);
				_status.currentAozhan=aozhan;
				if(aozhan.startsWith('db:')) game.getDB('image',aozhan.slice(3)).then(result=>ui.backgroundMusic.src=result);
				else if(aozhan.startsWith('ext:')) ui.backgroundMusic.src=`${lib.assetURL}extension/${aozhan.slice(4)}`;
				else ui.backgroundMusic.src=`${lib.assetURL}audio/background/aozhan_${aozhan}.mp3`;
				return;
			}
			let music=_status.tempMusic||lib.config.background_music;
			if(Array.isArray(music)) music=music.randomGet('music_off',_status.currentMusic)||lib.config.background_music;
			if(music=='music_random') music=lib.config.all.background_music.randomGet('music_off','music_random',_status.currentMusic);
			_status.currentMusic=music;
			if(music=='music_custom'){
				const backgroundMusicSourceConfiguration=lib.config.background_music_src;
				if(backgroundMusicSourceConfiguration) ui.backgroundMusic.src=backgroundMusicSourceConfiguration;
				return;
			}
			if(music.startsWith('db:')) game.getDB('image',music.slice(3)).then(result=>ui.backgroundMusic.src=result);
			else if(music.startsWith('ext:')) ui.backgroundMusic.src=`${lib.assetURL}extension/${music.slice(4)}`;
			else ui.backgroundMusic.src=`${lib.assetURL}audio/background/${music}.mp3`;
		},
		import:function(type,content,url){
			if(type=='extension'){
				const promise=game.loadExtension(content);
				if(typeof _status.extensionLoading=="undefined")_status.extensionLoading=[];
				_status.extensionLoading.add(promise);
				return promise;
			}
			else{
				if(!lib.imported[type])lib.imported[type]={};
				const promise=Promise.resolve((gnc.is.generator(content)?gnc.of(content):content)(lib,game,ui,get,ai,_status)).then(content2=>{
					if(content2.name){
						lib.imported[type][content2.name]=content2;
						delete content2.name;
					}
				});
				if(typeof _status.importing=="undefined")_status.importing={};
				if(!_status.importing[type])_status.importing[type]=[];
				_status.importing[type].add(promise);
				return promise;
			}
		},
		loadExtension:gnc.of(function*(object){
			let noEval=false;
			if(typeof object=='function'){
				object=yield (gnc.is.generatorFunc(object)?gnc.of(object):object)(lib,game,ui,get,ai,_status);
				noEval=true;
			}
			const name=object.name,extensionName=`extension_${name}`,extensionMenu=lib.extensionMenu[extensionName]={
				enable:{
					name:'开启',
					init:true
				}
			},objectPackage=object.package;
			if(objectPackage){
				const author=Object.getOwnPropertyDescriptor(objectPackage,'author');
				if(author) Object.defineProperty(extensionMenu.author={
					get name(){
						return `作者:${this.author}`;
					},
					clear:true,
					nopointer:true,
				},'author',author);
				const intro=Object.getOwnPropertyDescriptor(objectPackage,'intro');
				if(intro) Object.defineProperty(extensionMenu.intro={
					clear:true,
					nopointer:true,
				},'name',intro);
			}
			const objectConfig=object.config;
			if(objectConfig) Object.defineProperties(extensionMenu,Object.keys(objectConfig).reduce((propertyDescriptorMap,key)=>{
				propertyDescriptorMap[key]=Object.getOwnPropertyDescriptor(objectConfig,key);
				return propertyDescriptorMap;
			},{}));
			const help=object.help;
			if(help) Object.defineProperties(lib.help,Object.keys(help).reduce((propertyDescriptorMap,key)=>{
				propertyDescriptorMap[key]=Object.getOwnPropertyDescriptor(help,key);
				return propertyDescriptorMap;
			},{}));
			if(object.editable!==false&&lib.config.show_extensionmaker) extensionMenu.edit={
				name:'编辑此扩展',
				clear:true,
				onclick:()=>{
					if(game.editExtension&&lib.extensionPack&&lib.extensionPack[name]) game.editExtension(name);
					else alert('无法编辑未启用的扩展,请启用此扩展并重启后重试');
				}
			};
			extensionMenu.delete={
				name:'删除此扩展',
				clear:true,
				onclick:function(){
					if(this.innerHTML!='<span>确认删除</span>'){
						this.innerHTML='<span>确认删除</span>';
						new Promise(resolve=>setTimeout(resolve,1000)).then(()=>this.innerHTML='<span>删除此扩展</span>');
						return;
					}
					const page=this.parentNode,start=page.parentNode.previousSibling;
					page.remove();
					if(start){
						const pageInStart=Array.from(start.childNodes).find(childNode=>childNode.link==page);
						if(pageInStart){
							let active=false;
							if(pageInStart.classList.contains('active')) active=true;
							pageInStart.remove();
							if(active){
								start.firstChild.classList.add('active');
								start.nextSibling.appendChild(start.firstChild.link);
							}
						}
					}
					game.removeExtension(name);
					if(typeof object.onremove=='function') object.onremove();
				}
			}

			if(_status.importingExtension){
				game.importedPack=object;
				return;
			}
			const libConfig=lib.config;
			if(!object||!libConfig[`${extensionName}_enable`]) return;
			if(!noEval) lib.init.eval(object);
			const config=Object.keys(libConfig).reduce((constructingConfig,key)=>{
				if(key!=extensionName&&key.startsWith(extensionName)) constructingConfig[key.slice(11+name.length)]=libConfig[key];
				return constructingConfig;
			},{});
			try{
				let extensionPack=lib.extensionPack[name];
				if(objectPackage){
					extensionPack=lib.extensionPack[name]=objectPackage;
					objectPackage.files=object.files||{};
					const extensionPackFiles=objectPackage.files;
					if(!extensionPackFiles.character) extensionPackFiles.character=[];
					if(!extensionPackFiles.card) extensionPackFiles.card=[];
					if(!extensionPackFiles.skill) extensionPackFiles.skill=[];
				}
				else extensionPack=lib.extensionPack[name]={};
				const content=object.content,precontent=object.precontent;
				extensionPack.code={
					content:content,
					precontent:precontent,
					help:help,
					config:objectConfig
				}
				if(precontent){
					_status.extension=name;
					yield (gnc.is.generatorFunc(precontent)?gnc.of(precontent):precontent).call(object,config);
					delete _status.extension;
				}
				if(content) lib.extensions.push([name,content,config,_status.evaluatingExtension,objectPackage||{}]);
			}
			catch(e){
				console.log(e);
			}
		}),
		createDir:(directory,successCallback,errorCallback)=>{
			const paths=directory.split('/').reverse();
			if(window.resolveLocalFileSystemURL) return new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(lib.assetURL,resolve,reject)).then(directoryEntry=>{
				const redo=entry=>new Promise((resolve,reject)=>entry.getDirectory(paths.pop(),{
					create:true
				},resolve,reject)).then(resolvedDirectoryEntry=>{
					if(paths.length) return redo(resolvedDirectoryEntry);
					if(typeof successCallback=='function') successCallback();
				});
				return redo(directoryEntry);
			},reason=>{
				if(typeof errorCallback!='function') return Promise.reject(reason);
				errorCallback(reason);
			});
			const fs=require("fs");
			let path=__dirname;
			const redo=()=>{
				path+=`/${paths.pop()}`;
				return new Promise(resolve=>fs.exists(path,resolve)).then(exists=>{
					//不存在此目录
					if(!exists) return new Promise(resolve=>fs.mkdir(path,resolve));
				}).then(()=>{
					if(paths.length) return redo();
					if(typeof successCallback=='function') successCallback();
				});
			};
			return redo();
		},
		importExtension:gnc.of(function*(data,finishLoad,exportExtension,extensionPackage){
			//by 来瓶可乐加冰、Rintim、Tipx-L
			if(!window.JSZip)
				yield new Promise((resolve,reject)=>lib.init.js(`${lib.assetURL}game`,"jszip",resolve,reject));

			const zip=new JSZip();
			if(get.objtype(data)=='object'){
				//导出
				const _filelist=data._filelist,filelist2=_filelist||[];
				if(_filelist) delete data._filelist;
				const filelist=Object.keys(data);
				filelist.forEach(value=>zip.file(value,data[value]));
				game.print(filelist);
				game.print(filelist2);
				const generate=zip.generate({
					type:'arraybuffer'
				});
				if(!exportExtension){
					game.importExtension.apply(this,[generate,finishLoad]);
					return;
				}
				if(extensionPackage){
					extensionPackage.files=filelist.concat(filelist2).filter(value=>value!='extension.js');
					const size=generate.byteLength;
					if(size<1000) extensionPackage.size=`${size}B`;
					else if(size<1000000) extensionPackage.size=`${Math.round(size/1000)}KB`;
					else extensionPackage.size=`${Math.round(size/100000)/10}MB`;
					zip.file('package.js',Object.keys(extensionPackage).reduce((constructingData,key,currentIndex,keys)=>`${constructingData}\t${key}:${JSON.stringify(extensionPackage[key])}${currentIndex<keys.length-1?',\n':'\n};'}`,`extension["${exportExtension}"]={\n`));
				}
				const blob=zip.generate({
					type:'blob'
				}),fileNameToSaveAs=`${exportExtension.replace(/\\|\/|\:|\?|\"|\*|<|>|\|/g,'-')}.zip`;

				if(lib.device){
					const directory=lib.device=='android'?cordova.file.externalDataDirectory:cordova.file.documentsDirectory;
					new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(directory,resolve,reject)).then(directoryEntry=>new Promise((resolve,reject)=>directoryEntry.getFile(fileNameToSaveAs,{
						create:true
					},resolve,reject))).then(fileEntry=>new Promise((resolve,reject)=>fileEntry.createWriter(resolve,reject))).then(fileWriter=>new Promise((resolve,reject)=>{
						fileWriter.onerror=reject;
						fileWriter.onwriteend=resolve;
						fileWriter.write(blob);
					})).then(()=>alert(`文件已导出至${directory}${fileNameToSaveAs}`));
				}
				else{
					const downloadLink=document.createElement('a');
					downloadLink.download=fileNameToSaveAs;
					downloadLink.innerHTML='Download File';
					downloadLink.href=window.URL.createObjectURL(blob);
					downloadLink.click();
				}

				if(typeof finishLoad=='function') finishLoad();
				return;
			}
			//导入
			const UHP=error=>alert(`导入失败:\n${JSON.stringify(error,null,'\t')}`);
			try{
				zip.load(data);
				// alert(zip.file('文件夹/加扩展.js').asText())
				const str=zip.file('extension.js').asText();
				if(str===""||undefined) throw('你导入的不是扩展!请选择正确的文件');
				_status.importingExtension=true;
				eval(str);
				yield Promise.allSettled(_status.extensionLoading);
				delete _status.extensionLoading;
				_status.importingExtension=false;
				if(!game.importedPack) throw('err');
				const extensionName=game.importedPack.name;
				if(lib.config.all.plays.contains(extensionName)) throw('禁止安装游戏原生扩展');
				const extensions=lib.config.extensions;
				if(extensions.contains(extensionName)) game.removeExtension(extensionName,true);
				extensions.add(extensionName);
				game.saveConfigValue('extensions');
				game.saveConfig(`extension_${extensionName}_enable`,true);
				const config=game.importedPack.config;
				Object.keys(config).forEach(value=>{
					const configObject=config[value];
					if(configObject&&configObject.hasOwnProperty('init')) game.saveConfig(`extension_${extensionName}_${value}`,configObject.init);
				});
				if(game.download){
					const files=zip.files,hiddenFileFlags=['.','_'],fileList=Object.keys(files).filter(key=>!files[key].dir&&!hiddenFileFlags.includes(key[0])).reverse();
					//alert(filelist)
					//电脑端
					//具备nodeJS环境
					if(lib.node&&lib.node.fs){
						const writeFile=errnoException=>{
							if(errnoException){
								finishLoad();
								UHP(errnoException);
								return;
							}
							if(fileList.length){
								//filename 数组 ...dir+/+file
								//这里需要个创文件夹的函数
								const zipDir=fileList.pop(),fileName=zipDir.split('/'),name=fileName.pop(),letGo=name=>new Promise(resolve=>lib.node.fs.writeFile(`${__dirname}/extension/${extensionName}/${name}`,zip.file(zipDir).asNodeBuffer(),null,resolve)).then(writeFile);
								return (fileName.length?game.createDir(`extension/${extensionName}/${fileName.join("/")}`).then(()=>letGo(`${fileName.join('/')}/${name}`)):letGo(name));
							}
							finishLoad();
						}
						game.ensureDirectory(`extension/${extensionName}`).then(writeFile).catch(UHP);
					}
					else new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(lib.assetURL,resolve,reject)).then(directoryEntry=>new Promise((resolve,reject)=>directoryEntry.getDirectory(`extension/${extensionName}`,{
						create:true
					},resolve,reject))).then(directoryEntry=>{
						//扩展文件夹
						const writeFile=()=>{
							if(!fileList.length){
								finishLoad();
								return;
							}
							//filename 数组 ...dir+/+file
							const zipDirectory=fileList.shift(),fileName=zipDirectory.split("/"),name=fileName.pop(),letGo=name=>new Promise((resolve,reject)=>directoryEntry.getFile(name,{
								create:true
							},resolve,reject)).then(fileEntry=>new Promise((resolve,reject)=>fileEntry.createWriter(resolve,reject))).then(fileWriter=>new Promise((resolve,reject)=>{
								fileWriter.onerror=reject;
								fileWriter.onwriteend=resolve;													
								fileWriter.write(zip.file(zipDirectory).asArrayBuffer());
							})).then(writeFile);
							return (fileName.length?game.createDir(`extension/${extensionName}/${fileName.join('/')}`).then(()=>letGo(`${fileName.join('/')}/${name}`)):letGo(name));
						};
						return writeFile();
					}).catch(UHP);
				}
				else{
					localStorage.setItem(`${lib.configprefix}extension_${extensionName}`,str);
					const hiddenFileFlags=['.','_'],fileList=Object.keys(zip.files).filter(filePath=>!hiddenFileFlags.includes(filePath[0])&&filePath[filePath.length-1]!='/');
					if(fileList.length&&lib.db){
						lib.config.extensionInfo[extensionName]={
							file:fileList
						};
						game.saveConfigValue('extensionInfo');
						fileList.forEach(filePath=>{
							const arrayBuffer=zip.file(filePath).asArrayBuffer();
							if(!arrayBuffer) return;
							const blob=new Blob([arrayBuffer]);
							new Promise((resolve,reject)=>{
								const fileReader=new FileReader();
								fileReader.onerror=reject;
								fileReader.onload=resolve;
								fileReader.readAsDataURL(blob,'UTF-8');
							}).then(fileLoadedEvent=>game.putDB('image',`extension-${extensionName}:${filePath}`,fileLoadedEvent.target.result));
						});
					}
					finishLoad();
				}
				delete game.importedPack;
			}
			catch(error){
				UHP(error);
				return false;
			}
		}),
		export:function(textToWrite,name){
			var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
			var fileNameToSaveAs = name||'noname';
			fileNameToSaveAs=fileNameToSaveAs.replace(/\\|\/|\:|\?|\"|\*|<|>|\|/g,'.');

			if(lib.device){
				var directory;
				if(lib.device=='android'){
					directory=cordova.file.externalDataDirectory;
				}
				else{
					directory=cordova.file.documentsDirectory;
				}
				window.resolveLocalFileSystemURL(directory,function(entry){
					entry.getFile(fileNameToSaveAs,{create:true},function(fileEntry){
						fileEntry.createWriter(function(fileWriter){
							fileWriter.onwriteend=function(){
								alert('文件已导出至'+directory+fileNameToSaveAs);
							}
							fileWriter.write(textFileAsBlob)
						});
					});
				});
			}
			else{
				var downloadLink = document.createElement("a");
				downloadLink.download = fileNameToSaveAs;
				downloadLink.innerHTML = "Download File";
				downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
				downloadLink.click();
			}
		},
		multiDownload2:function(list,onsuccess,onerror,onfinish,process,dev){
			list=list.slice(0);
			var download=function(){
				if(list.length){
					var current=list.shift();
					var current2;
					if(typeof process=='function'){
						current2=process(current);
					}
					else{
						current2=current;
					}
					if(current.startsWith('theme')){
						game.print(current.slice(6));
					}
					else if(current.startsWith('image/skin')){
						game.print(current.slice(11));
					}
					else{
						game.print(current.slice(current.lastIndexOf('/')+1));
					}
					game.download(current,current2,function(){
						if(onsuccess) onsuccess(list.length);
						download();
					},function(){
						if(onerror) onerror(list.length);
						download();
					},dev);
				}
				else{
					if(onfinish) onfinish();
				}
			}
			download();
		},
		multiDownload:function(list,onsuccess,onerror,onfinish,process,dev){
			if(lib.config.dev) game.print(get.url());
			var args=Array.from(arguments);
			if(list.length<=3){
				game.multiDownload2.apply(this,args);
			}
			else{
				var num=Math.round(list.length/3);
				var left=3;
				args[3]=function(){
					left--;
					if(left==0){
						onfinish();
					}
				};
				setTimeout(function(){
					args[0]=list.slice(0,num);game.multiDownload2.apply(game,args);
				});
				setTimeout(function(){
					args[0]=list.slice(num,2*num);game.multiDownload2.apply(this,args);
				},200);
				setTimeout(function(){
					args[0]=list.slice(2*num);game.multiDownload2.apply(this,args);
				},400);
			}
		},
		fetch:function(url,onload,onerror,onprogress){
			var tmpName='~tmp'+get.id();
			game.download(encodeURI(url),tmpName,function(){
				game.readFile(tmpName,function(data){
					onload(data);
					game.removeFile(tmpName);
				},onerror);
			},onerror,null,onprogress);
		},
		playVideo:function(time,mode){
			if(!_status.replayvideo){
				localStorage.setItem(lib.configprefix+'playbackmode',lib.config.mode);
			}
			game.saveConfig('mode',mode);
			localStorage.setItem(lib.configprefix+'playback',time);
			game.reload();
		},
		playVideoContent:function(video){
			var next=game.createEvent('video',false);
			next.video=video;
			ui.system.style.display='none';
			ui.system.hide();
			ui.arena.style.display='none';
			ui.arena.hide();
			ui.window.classList.remove('leftbar');
			ui.window.classList.remove('rightbar');
			ui.historybar.style.display='none';
			_status.event=next;
			_status.paused=false;
			_status.paused2=false;
			_status.over=false;
			_status.video=true;
			clearTimeout(_status.timeout);

			for(var i in lib.characterPack){
				for(var j in lib.characterPack[i]){
					lib.character[j]=lib.character[j]||lib.characterPack[i][j];
				}
			}
			next.setContent('playVideoContent');
			game.loop();
		},
		videoContent:{
			arrangeLib:function(content){
				for(var i in content){
					for(var j in content[i]){
						lib[i][j]=content[i][j];
					}
				}
			},
			$syncDisable:function(player,map){
				player.disabledSlots=map;
				player.$syncDisable(map)
			},
			$syncExpand:function(player,map){
				player.expandedSlots=map;
				player.$syncExpand(map)
			},
			$disableJudge:function(player,map){
				player.$disableJudge()
			},
			$enableJudge:function(player,map){
				player.$enableJudge()
			},
			jiuNode:function(player,bool){
				//Powered by 升麻
				if(bool){
					if(!player.node.jiu&&lib.config.jiu_effect){
						player.node.jiu=ui.create.div('.playerjiu',player.node.avatar);
						player.node.jiu2=ui.create.div('.playerjiu',player.node.avatar2);
					}
				}
				else{
					if(player.node.jiu){
						player.node.jiu.delete();
						player.node.jiu2.delete();
						delete player.node.jiu;
						delete player.node.jiu2;
					}
				}
			},
			init:function(players){
				if(game.chess) return;
				if(lib.config.mode=='versus'){
					players.bool=players.pop();
				}
				ui.arena.setNumber(players.length);
				ui.arena.classList.add('video');
				game.players.length=0;
				game.dead.length=0;
				ui.create.players(players.length);
				game.me=game.players[0];
				ui.handcards1=game.me.node.handcards1;
				ui.handcards2=game.me.node.handcards2;
				ui.handcards1Container.appendChild(ui.handcards1);
				ui.handcards2Container.appendChild(ui.handcards2);
				if(lib.config.mode=='versus'){
					if(players.bool){
						ui.arena.setNumber(parseInt(ui.arena.dataset.number)+1);
						for(var i=0;i<game.players.length;i++){
							game.players[i].dataset.position=parseInt(game.players[i].dataset.position)+1;
						}
						game.singleHandcard=true;
						ui.arena.classList.add('single-handcard');
						ui.window.classList.add('single-handcard');
						ui.fakeme=ui.create.div('.fakeme.avatar',ui.me);
					}
					ui.arena.style.display='';
					ui.refresh(ui.arena);
					ui.arena.show();
				}
				else if(lib.config.mode=='boss'){
					if(!players.boss){
						game.singleHandcard=true;
						ui.arena.classList.add('single-handcard');
						ui.window.classList.add('single-handcard');
						ui.fakeme=ui.create.div('.fakeme.avatar',ui.me);
					}
					ui.arena.setNumber(8);
				}
				ui.updatehl();
				for(var i=0;i<players.length;i++){
					if(lib.config.mode=='identity'){
						game.players[i].init(players[i].name,players[i].name2);
						game.players[i].setIdentity(players[i].identity);
					}
					else if(lib.config.mode=='doudizhu'||lib.config.mode=='single'){
						game.players[i].init(players[i].name,players[i].name2);
						game.players[i].setIdentity(players[i].identity);
					}
					else if(lib.config.mode=='stone'){
						game.players[i].init(players[i].name,players[i].name2);
						game.players[i].classList.add('noidentity');
						game.players[i].updateActCount(null,players[i].count,0);
					}
					else if(lib.config.mode=='boss'){
						game.players[i].init(players[i].name,players[i].name2);
						game.players[i].setIdentity(players[i].identity);
						game.players[i].dataset.position=players[i].position;
						game.players[i].node.action.innerHTML='行动';
					}
					else if(lib.config.mode=='versus'){
						game.players[i].init(players[i].name,players[i].name2);
						game.players[i].node.identity.firstChild.innerHTML=players[i].identity;
						game.players[i].node.identity.dataset.color=players[i].color;
						game.players[i].node.action.innerHTML='行动';
					}
					else if(lib.config.mode=='guozhan'){
						game.players[i].name=players[i].name;
						game.players[i].name1=players[i].name1;
						game.players[i].name2=players[i].name2;

						game.players[i].sex='unknown';
						game.players[i].identity='unknown';

						lib.translate[game.players[i].name]=players[i].translate;
						game.players[i].init(players[i].name1,players[i].name2);

						game.players[i].classList.add('unseen_v');
						game.players[i].classList.add('unseen2_v');
						if(game.players[i]!=game.me){
							game.players[i].node.identity.firstChild.innerHTML='猜';
							game.players[i].node.identity.dataset.color='unknown';
						}
						else{
							game.players[i].setIdentity(game.players[i].group);
						}
					}
				}
				for(var i=0;i<game.players.length;i++){
					game.playerMap[game.players[i].dataset.position]=game.players[i];
				}

				if(lib.config.mode=='versus'){
					if(players.bool){
						game.onSwapControl();
					}
				}
				else if(lib.config.mode=='boss'){
					if(!players.boss){
						game.onSwapControl();
					}
					ui.arena.style.display='';
					ui.refresh(ui.arena);
					ui.arena.show();
					ui.updatehl();
				}
			},
			newcard:function(content){
				if(content){
					lib.translate[content.name]=content.translate;
					lib.translate[content.name+'_info']=content.info;
					lib.card[content.name]={};
					lib.card[content.name].cardimage=content.card
					for(var i in lib.card[content.card]){
						lib.card[content.name][i]=lib.card[content.card][i];
					}
					if(content.legend){
						lib.card[content.name].legend=true;
					}
					else if(content.epic){
						lib.card[content.name].epic=true;
					}
					else if(content.unique){
						lib.card[content.name].unique=true;
					}
				}
			},
			changeLand:function(player,url){
				game.changeLand(url,player);
			},
			destroyLand:function(){
				if(ui.land){
					ui.land.destroy();
				}
			},
			playAudio:function(str){
				game.playAudio(str,'video');
			},
			playSkillAudio:function(name){
				game.playSkillAudio(name,'video');
			},
			phaseChange:function(player){
				if(player){
					var glowing=document.querySelector('.glow_phase');
					if(glowing){
						glowing.classList.remove('glow_phase');
					}
					if(lib.config.glow_phase){
						player.classList.add('glow_phase');
						// player.dataset.glow_phase=lib.config.glow_phase;
					}
				}
				else{
					console.log(player);
				}
			},
			playerfocus:function(player,time){
				if(player&&player.playerfocus){
					player.playerfocus(time);
				}
				else{
					console.log(player);
				}
			},
			playerfocus2:function(){
				ui.arena.classList.add('playerfocus');
				setTimeout(function(){
					ui.arena.classList.remove('playerfocus');
				},1500)
			},
			identityText:function(player,str){
				if(player&&str){
					player.node.identity.firstChild.innerHTML=str;
				}
				else{
					console.log(player);
				}
			},
			identityColor:function(player,str){
				if(player&&str){
					player.node.identity.dataset.color=str;
				}
				else{
					console.log(player);
				}
			},
			chessSwap:function(content){
				var me=game.playerMap[content[0]];
				var player=game.playerMap[content[1]];
				if(me){
					me.classList.remove('current_action');
				}
				if(player){
					player.classList.add('current_action');
				}
			},
			chessgainmod:function(player,num){
				if(Array.isArray(num)){
					num=get.infoCards(num);
				}
				if(player&&player.$gainmod){
					player.$gainmod(num);
				}
				else{
					console.log(player);
				}
			},
			moveTo:function(player,pos){
				if(player&&player.moveTo&&pos){
					player.moveTo(pos[0],pos[1]);
				}
				else{
					console.log(player)
				}
			},
			addObstacle:function(pos){
				if(pos){
					game.addObstacle(pos[0],pos[1]);
				}
			},
			removeObstacle:function(pos){
				game.removeObstacle(pos);
			},
			moveObstacle:function(pos){
				if(pos){
					game.moveObstacle(pos[0],pos[1],pos[2]);
				}
			},
			colorObstacle:function(pos){
				if(pos){
					game.colorObstacle(pos[0],pos[1]);
				}
			},
			thrownhighlight1:function(){
				ui.arena.classList.add('thrownhighlight');
			},
			thrownhighlight2:function(){
				ui.arena.classList.remove('thrownhighlight');
			},
			chessFocus:function(player){
				if(player){
					player.chessFocus();
				}
				else{
					console.log('chessFocus');
				}
			},
			removeTreasure:function(pos){
				if(game.playerMap[pos]){
					game.playerMap[pos].delete();
					delete game.playerMap[pos];
				}
				else{
					console.log(pos);
				}
			},
			initobs:function(obs){
				if(obs){
					for(var i=0;i<obs.length;i++){
						game.addObstacle(obs[i]);
					}
				}
				else{
					console.log(obs);
				}
			},
			stonePosition:function(content){
				var player=game.playerMap[content[0]];
				if(player){
					delete game.playerMap[content[0]];
					player.dataset.position=content[1];
					game.playerMap[content[1]]=player;
				}
				else{
					console.log(content);
				}
			},
			bossSwap:function(player,name){
				if(player&&name){
					player.delete();
					var noboss=false;
					if(name[0]=='_'){
						name=name.slice(1);
						noboss=true;
					}
					var boss=ui.create.player().init(name);
					boss.dataset.position=player.dataset.position;
					game.playerMap[player.dataset.position]=boss;
					if(game.me==player){
						game.me=boss;
					}
					game.players.push(boss);
					game.arrangePlayers();
					if(!noboss){
						game.boss=boss;
						boss.setIdentity('zhu');
						boss.identity='zhu';
					}
					else{
						boss.setIdentity('zhong');
						boss.identity='zhong';
					}
					ui.arena.appendChild(boss.animate('zoominanim'));
				}
			},
			stoneSwap:function(info){
				var player=ui.create.player();
				player.classList.add('noidentity');
				player.dataset.position=info.position;
				player.animate(info.me?'replaceme':'replaceenemy');
				player.actcount=info.actcount;
				player.init(info.name,info.name2);
				game.players.push(player);
				player.updateActCount(null,info.actcount,0);
				ui.arena.appendChild(player);
				game.playerMap[player.dataset.position]=player;
				game.arrangePlayers();
			},
			chess_tongshuai:function(player,content){
				if(player&&player.storage){
					player.storage.tongshuai.owned=content;
				}
				else{
					console.log(player);
				}
			},
			chess_tongshuai_skill:function(player,content){
				if(player&&content){
					if(player.marks.tongshuai.firstChild){
						player.marks.tongshuai.firstChild.remove();
					}
					player.marks.tongshuai.setBackground(content[0],'character');
					player.additionalSkills.tongshuai=content[1];
				}
				else{
					console.log(player);
				}
			},
			smoothAvatar:function(player,vice){
				if(player&&player.node){
					if(vice){
						if(player.node.avatar2){
							player.smoothAvatar(vice);
						}
					}
					else{
						if(player.node.avatar){
							player.smoothAvatar(vice);
						}
					}
				}
			},
			setAvatar:function(player,content){
				if(player&&content&&content.length==2){
					player.setAvatar(content[0],content[1])
				}
			},
			setAvatarQueue:function(player,content){
				if(player&&content&&content.length==2){
					player.setAvatarQueue(content[0],content[1])
				}
			},
			addSubPlayer:function(player,content){
				if(player&&content&&content[0]&&content[1]&&
					content[2]&&content[3]&&content[4]){
					var skill=content[0];
					lib.skill[skill]=content[1];
					lib.character[skill]=content[2];
					lib.translate[skill]=content[3];
					player.storage[skill]=content[4];
				}
			},
			arenaNumber:function(content){
				ui.arena.dataset.number=content;
			},
			reinit:function(source,content){
				if(source&&content){
					source.uninit();
					source.init(content[0]);
					source.node.identity.dataset.color=content[1];
				}
				else{
					console.log(source);
				}
			},
			reinit2:function(source,name){
				if(source&&name){
					source.init(name);
				}
				else{
					console.log(source);
				}
			},
			reinit3:function(source,content){
				if(source&&content){
					var info1=lib.character[content.from];
					var info2=lib.character[content.to];
					if(content.avatar2){
						source.name2=content.to;
						if(source.isUnseen(0)){
							source.sex=info2[0];
						}
						source.node.avatar2.setBackground(content.to,'character');
						source.node.name2.innerHTML=get.slimName(content.to);
					}
					else{
						source.name=content.to;
						source.sex=info2[0];
						source.node.avatar.setBackground(content.to,'character');
						source.node.name.innerHTML=get.slimName(content.to);
					}
					source.maxHp=content.hp;
					this.update();
					for(var i=0;i<info1[3].length;i++){
						source.removeSkill(info1[3][i]);
					}
					for(var i=0;i<info2[3].length;i++){
						source.addSkill(info2[3][i]);
					}
				}
			},
			skill:function(player,content){
				if(typeof content=='string'){
					if(lib.skill[content]) lib.skill[content].video(player);
				}
				else if(Array.isArray(content)){
					if(lib.skill[content[0]]) lib.skill[content[0]].video(player,content[1]);
				}
				else{
					console.log(player,content)
				}
			},
			addFellow:function(content){
				var player=game.addFellow(content[0],content[1],content[2]);
				game.playerMap[player.dataset.position]=player;
			},
			windowzoom1:function(){
				ui.window.style.transition='all 0.5s';
				ui.window.classList.add('zoomout3');
				ui.window.hide();
			},
			windowzoom2:function(){
				ui.window.style.transition='all 0s';
				ui.refresh(ui.window);
			},
			windowzoom3:function(){
				ui.window.classList.remove('zoomout3');
				ui.window.classList.add('zoomin3');
			},
			windowzoom4:function(){
				ui.window.style.transition='all 0.5s';
				ui.refresh(ui.window);
				ui.window.show();
				ui.window.classList.remove('zoomin3');
			},
			windowzoom5:function(){
				ui.window.style.transition='';
			},
			updateActCount:function(player,content){
				if(player&&content){
					player.updateActCount(content[0],content[1],content[2]);
				}
				else{
					console.log(player);
				}
			},
			setIdentity:function(player,identity){
				if(player&&identity){
					player.setIdentity(identity);
				}
				else{
					console.log(num);
				}
			},
			showCharacter:function(player,num){
				if(player&&player.classList){
					switch(num){
						case 0:
						player.classList.remove('unseen_v');
						break;
						case 1:
						player.classList.remove('unseen2_v');
						break;
						case 2:
						player.classList.remove('unseen_v');
						player.classList.remove('unseen2_v');
						break;
					}
					if(!player.classList.contains('unseen_v')&&(!player.name2||!player.classList.contains('unseen2_v'))&&player.storage.nohp){
						delete player.storage.nohp;
						player.node.hp.show();
						player.update();
					}
				}
				else{
					console.log(num);
				}
			},
			hidePlayer:function(player){
				if(player){
					player.hide();
				}
			},
			deleteHandcards:function(player){
				if(player){
					player.node.handcards1.delete();
					player.node.handcards2.delete();
				}
			},
			hideCharacter:function(player,num){
				if(player&&player.classList){
					switch(num){
						case 0:
						player.classList.add('unseen_v');
						break;
						case 1:
						player.classList.add('unseen2_v');
						break;
						case 2:
						player.classList.add('unseen_v');
						player.classList.add('unseen2_v');
						break;
					}
				}
				else{
					console.log(num);
				}
			},
			popup:function(player,info){
				if(player&&info){
					player.popup(info[0],info[1]);
				}
				else{
					console.log(player);
				}
			},
			log:function(str){
				game.log(str);
			},
			draw:function(player,info){
				if(player&&player.$draw){
					player.$draw(info);
				}
				else{
					console.log(player);
				}
			},
			drawCard:function(player,info){
				if(player&&info){
					player.$draw(get.infoCards(info));
				}
				else{
					console.log(player);
				}
			},
			throw:function(player,info){
				if(player&&info){
					player.$throw(get.infoCards(info[0]),info[1],null,info[2]);
				}
				else{
					console.log(player);
				}
			},
			compare:function(player,info){
				if(player&&info){
					player.$compare(get.infoCard(info[0]),game.playerMap[info[1]],get.infoCard(info[2]));
				}
				else{
					console.log(player);
				}
			},
			compareMultiple:function(player,info){
				if(player&&info){
					player.$compareMultiple(get.infoCard(info[0]),get.infoTargets(info[1]),get.infoCards(info[2]));
				}
				else{
					console.log(player);
				}
			},
			give:function(player,info){
				if(player&&info){
					player.$give(info[0],game.playerMap[info[1]]);
				}
				else{
					console.log(player);
				}
			},
			giveCard:function(player,info){
				if(player&&info){
					player.$give(get.infoCards(info[0]),game.playerMap[info[1]]);
				}
				else{
					console.log(player);
				}
			},
			gain:function(player,info){
				if(player&&player.$gain){
					player.$gain(info);
				}
				else{
					console.log(player);
				}
			},
			gainCard:function(player,info){
				if(player&&info){
					player.$gain(get.infoCards(info));
				}
				else{
					console.log(player);
				}
			},
			gain2:function(player,cards){
				if(player&&player.$draw){
					var nodeList=document.querySelectorAll('#arena>.card,#chess>.card');
					var nodes=[];
					for(var i=0;i<nodeList.length;i++){
						nodes.push(nodeList[i]);
					}
					for(var i=0;i<cards.length;i++){
						for(var j=0;j<nodes.length;j++){
							if(cards[i][2]==nodes[j].name&&cards[i][0]==nodes[j].suit&&cards[i][1]==nodes[j].number){
								nodes[j].moveDelete(player);
								cards.splice(i--,1);
								nodes.splice(j--,1);
								break;
							}
						}
					}
					if(cards.length){
						player.$draw(get.infoCards(cards));
					}
				}
				else{
					console.log(player);
				}
			},
			deletenode:function(player,cards,method){
				if(cards){
					var nodeList=document.querySelectorAll('#arena>.card,#chess>.card');
					var nodes=[];
					for(var i=0;i<nodeList.length;i++){
						nodes.push(nodeList[i]);
					}
					for(var i=0;i<cards.length;i++){
						for(var j=0;j<nodes.length;j++){
							if(cards[i][2]==nodes[j].name&&cards[i][0]==nodes[j].suit&&cards[i][1]==nodes[j].number){
								nodes[j].delete();
								if(method=='zoom'){
									nodes[j].style.transform='scale(0)';
								}
								cards.splice(i--,1);
								nodes.splice(j--,1);
								break;
							}
						}
					}
				}
				else{
					console.log(player,cards);
				}
			},
			highlightnode:function(player,card){
				if(card){
					var nodeList=document.querySelectorAll('#arena>.card,#chess>.card');
					var nodes=[];
					for(var i=0;i<nodeList.length;i++){
						nodes.push(nodeList[i]);
					}
					for(var j=nodes.length-1;j>=0;j--){
						if(card[2]==nodes[j].name&&card[0]==nodes[j].suit&&card[1]==nodes[j].number){
							nodes[j].classList.add('thrownhighlight');
							break;
						}
					}
				}
				else{
					console.log(player,cards);
				}
			},
			uiClear:function(){
				ui.clear();
			},
			judge1:function(player,content){
				if(player&&content){
					var judging=get.infoCard(content[0]);
					if(game.chess){
						judging.copy('thrown','center','thrownhighlight',ui.arena).animate('start');
					}
					else{
						player.$throwordered(judging.copy('thrownhighlight'),true);
					}

					ui.create.dialog(content[1]).videoId=content[2];
					ui.arena.classList.add('thrownhighlight');
				}
				else{
					console.log(player);
				}
			},
			centernode:function(content){
				get.infoCard(content).copy('thrown','center','thrownhighlight',ui.arena).animate('start');
			},
			judge2:function(videoId){
				for(var i=0;i<ui.dialogs.length;i++){
					if(ui.dialogs[i].videoId==videoId){
						ui.dialogs[i].close();
					}
				}
				ui.arena.classList.remove('thrownhighlight');
			},
			unmarkname:function(player,name){
				if(player&&player.unmark){
					player.unmark(name);
				}
				else{
					console.log(player);
				}
			},
			unmark:function(player,name){
				if(player&&player.marks&&player.marks[name]){
					player.marks[name].delete();
					player.marks[name].style.transform+=' scale(0.2)';
					delete player.marks[name];
					ui.updatem(this);
				}
			},
			flame:function(player,type){
				if(player&&type){
					player['$'+type]();
				}
				else{
					console.log(player);
				}
			},
			throwEmotion:function(player,content){
				if(player&&content){
					player.$throwEmotion(game.playerMap[content[0]],content[1]);
				}
				else{
					console.log(player);
				}
			},
			addGaintag:function(player,content){
				if(player&&content){
					var checkMatch=function(l1,l2){
						for(var i=0;i<l1.length;i++){
							for(var j=0;j<l2.length;j++){
								if(l2[j].suit==l1[i][0]&&l2[j].number==l1[i][1]&&l2[j].name==l1[i][2]){
									l2[j].addGaintag(content[1]);
									l2.splice(j--,1);
									break;
								}
							}
						}
					}
					checkMatch(content[0],player.getCards('h'));
				}
				else{
					console.log(player);
				}
			},
			removeGaintag:function(player,content){
				if(player&&content){
					if(Array.isArray(content)) player.removeGaintag.apply(player,content)
					else player.removeGaintag(content);
				}
				else{
					console.log(player);
				}
			},
			line:function(player,content){
				if(player&&content){
					player.line(game.playerMap[content[0]],content[1]);
				}
				else{
					console.log(player);
				}
			},
			fullscreenpop:function(player,content){
				if(player&&content){
					player.$fullscreenpop(content[0],content[1],content[2]);
				}
				else{
					console.log(player);
				}
			},
			damagepop:function(player,content){
				if(player&&content){
					player.$damagepop(content[0],content[1],content[2]);
				}
				else{
					console.log(player);
				}
			},
			damage:function(player,source){
				if(player&&player.$damage){
					player.$damage(game.playerMap[source]);
				}
				else{
					console.log(player);
				}
			},
			diex:function(player){
				if(!player){
					console.log('diex');
					return;
				}
				var cards=player.getCards('hej');
				for(var i=0;i<cards.length;i++){
					cards[i].discard();
				}
				while(player.node.marks.childNodes.length>1){
					player.node.marks.lastChild.remove();
				}
				player.classList.add('dead');
				player.classList.remove('turnedover');
				player.classList.remove('out');
				player.node.count.innerHTML='0';
				player.node.hp.hide();
				player.node.equips.hide();
				player.node.count.hide();
				player.previous.next=player.next;
				player.next.previous=player.previous;
				game.players.remove(player);
				game.dead.push(player);
				if(lib.config.mode=='stone'){
					setTimeout(function(){
						player.delete();
					},500);
				}
			},
			tafangMe:function(player){
				if(player){
					game.me=player;
					ui.me.lastChild.show();
					ui.create.fakeme();
					ui.handcards1=player.node.handcards1.animate('start').fix();
					ui.handcards2=player.node.handcards2.animate('start').fix();
					ui.handcards1Container.appendChild(ui.handcards1);
					ui.handcards2Container.appendChild(ui.handcards2);
					ui.updatehl();
					game.setChessInfo();
				}
			},
			deleteChessPlayer:function(player){
				if(player){
					player.delete();
					delete game.playerMap[player.dataset.position];
					game.players.remove(player);
					for(var i=0;i<ui.phasequeue.length;i++){
						if(ui.phasequeue[i].link==player){
							ui.phasequeue[i].remove();
							ui.phasequeue.splice(i,1);
							break;
						}
					}
				}
			},
			addChessPlayer:function(content){
				game.addChessPlayer.apply(this,content);
			},
			die:function(player){
				if(!player){
					console.log('die');
					return;
				}
				player.$die();
				if(game.chess){
					delete lib.posmap[player.dataset.position];
					setTimeout(function(){
						player.delete();
					},500);
					for(var i=0;i<ui.phasequeue.length;i++){
						if(ui.phasequeue[i].link==player){
							ui.phasequeue[i].remove();
							ui.phasequeue.splice(i,1);
							break;
						}
					}
				}
			},
			revive:function(player){
				if(!player){
					console.log('revive');
					return;
				}
				player.classList.remove('dead');
				player.node.hp.show();
				player.node.equips.show();
				player.node.count.show();
				player.node.avatar.style.transform='';
				player.node.avatar2.style.transform='';
				player.removeAttribute('style');
			},
			update:function(player,info){
				if(player&&info){
					player.hp=info[1];
					player.maxHp=info[2];
					player.hujia=info[3];
					player.update(info[0]);
				}
				else{
					console.log(player);
				}
			},
			phaseJudge:function(player,card){
				if(player&&card){
					// player.$phaseJudge(get.infoCard(card));
				}
				else{
					console.log(player);
				}
			},
			directgain:function(player,cards){
				if(player&&cards){
					player.directgain(get.infoCards(cards));
				}
				else{
					console.log(player);
				}
			},
			directgains:function(player,cards){
				if(player&&cards){
					player.directgains(get.infoCards(cards));
				}
				else{
					console.log(player);
				}
			},
			directequip:function(player,cards){
				if(player&&cards){
					player.directequip(get.infoCards(cards));
				}
				else{
					console.log(player);
				}
			},
			gain12:function(player,cards12){
				if(player&&cards12){
					var cards1=get.infoCards(cards12[0]);
					var cards2=get.infoCards(cards12[1]);
					for(var i=0;i<cards1.length;i++){
						cards1[i].classList.add('drawinghidden');
						cards1[i].addGaintag(cards12[2]);
						player.node.handcards1.insertBefore(cards1[i],player.node.handcards1.firstChild);
					}
					for(var i=0;i<cards2.length;i++){
						cards2[i].classList.add('drawinghidden');
						cards2[i].addGaintag(cards12[2]);
						player.node.handcards2.insertBefore(cards2[i],player.node.handcards2.firstChild);
					}
					ui.updatehl();
				}
				else{
					console.log(player);
				}
			},
			equip:function(player,card){
				if(player&&card){
					player.$equip(get.infoCard(card));
				}
				else{
					console.log(player);
				}
			},
			addJudge:function(player,content){
				if(player&&content){
					var card=get.infoCard(content[0]);
					card.viewAs=content[1];
					if(card.viewAs&&card.viewAs!=card.name&&(card.classList.contains('fullskin')||card.classList.contains('fullborder'))){
						card.classList.add('fakejudge');
						card.node.background.innerHTML=lib.translate[card.viewAs+'_bg']||get.translation(card.viewAs)[0]
					}
					card.classList.add('drawinghidden');
					player.node.judges.insertBefore(card,player.node.judges.firstChild);
					ui.updatej(player);
				}
				else{
					console.log(player);
				}
			},
			markCharacter:function(player,content){
				if(player&&content){
					if(game.playerMap[content.target]){
						content.target=game.playerMap[content.target];
					}
					var mark=player.markCharacter(content.target,content);
					if(content.id){
						player.marks[content.id]=mark;
					}
				}
				else{
					console.log(player);
				}
			},
			changeMarkCharacter:function(player,content){
				if(player&&content&&player.marks[content.id]){
					player.marks[content.id].info={
						name:content.name,
						content:content.content
					};
					player.marks[content.id].setBackground(content.target,'character');
				}
			},
			mark:function(player,content){
				if(player&&content){
					var mark=player.mark(content.id,content);
				}
				else{
					console.log(player);
				}
			},
			markSkill:function(player,content){
				if(player&&content){
					if(content[1]){
						player.markSkill(content[0],null,get.infoCard(content[1]));
					}
					else{
						player.markSkill(content[0]);
					}
				}
				else{
					console.log(player);
				}
			},
			unmarkSkill:function(player,name){
				if(player&&player.unmarkSkill){
					player.unmarkSkill(name);
				}
				else{
					console.log(player);
				}
			},
			storage:function(player,content){
				if(player&&content){
					if(content[2]){
						switch(content[2]){
							case 'cards':content[1]=get.infoCards(content[1]);break;
							case 'card':content[1]=get.infoCard(content[1]);break;
						}
					}
					player.storage[content[0]]=content[1];
				}
				else{
					console.log(player);
				}
			},
			markId:function(player,content){
				if(player&&content){
					player.mark(get.infoCard(content[0]),content[1]);
				}
				else{
					console.log(player);
				}
			},
			unmarkId:function(player,content){
				if(player&&content){
					player.unmark(get.infoCard(content[0]),content[1]);
				}
				else{
					console.log(player);
				}
			},
			lose:function(player,info){
				if(player&&info){
					var hs=info[0]||[],es=info[1]||[],js=info[2]||[],ss=info[3]||[];
					var phs=player.getCards('h'),pes=player.getCards('e'),pjs=player.getCards('j'),pss=player.getCards('s');
					var checkMatch=function(l1,l2){
						for(var i=0;i<l1.length;i++){
							for(var j=0;j<l2.length;j++){
								if(l2[j].suit==l1[i][0]&&l2[j].number==l1[i][1]&&l2[j].name==l1[i][2]){
									l2[j].remove();
									l2.splice(j--,1);
									break;
								}
							}
						}
					}
					checkMatch(hs,phs);
					checkMatch(es,pes);
					checkMatch(js,pjs);
					checkMatch(ss,pss);
					ui.updatehl();
				}
				else{
					console.log(player);
				}
			},
			loseAfter:function(player){
				if(!player){
					console.log('loseAfter');
					return;
				}
			},
			link:function(player,bool){
				if(player&&player.classList){
					if(bool){
						player.addLink();
					}
					else{
						player.removeLink();
					}
				}
				else{
					console.log(player);
				}
			},
			turnOver:function(player,bool){
				if(player&&player.classList){
					if(bool){
						player.classList.add('turnedover');
					}
					else{
						player.classList.remove('turnedover');
					}
				}
				else{
					console.log(player);
				}
			},
			showCards:function(player,info){
				if(info){
					var dialog=ui.create.dialog(info[0],get.infoCards(info[1]));
					setTimeout(function(){
						dialog.close();
					},1000);
				}
				else{
					console.log(player);
				}
			},
			cardDialog:function(content){
				if(Array.isArray(content)){
					ui.create.dialog(content[0],get.infoCards(content[1])).videoId=content[2];
				}
				else if(typeof content=='number'){
					for(var i=0;i<ui.dialogs.length;i++){
						if(ui.dialogs[i].videoId==content){
							ui.dialogs[i].close();
							return;
						}
					}
				}
			},
			changeSeat:function(player,info){
				if(player&&player.getBoundingClientRect&&player.changeSeat){
					player.changeSeat(info);
					game.playerMap={};
					var players=game.players.concat(game.dead);
					for(var i=0;i<players.length;i++){
						game.playerMap[players[i].dataset.position]=players[i];
					}
				}
			},
			dialogCapt:function(content){
				for(var i=0;i<ui.dialogs.length;i++){
					if(ui.dialogs[i].videoId==content[0]){
						ui.dialogs[i].content.firstChild.innerHTML=content[1];
						return;
					}
				}
			},
			swapSeat:function(content){
				var player1=game.playerMap[content[0]];
				var player2=game.playerMap[content[1]];
				if(!player1||!player2){
					console.log(content);
					return;
				}
				var temp1,pos,i,num;
				temp1=player1.dataset.position;
				player1.dataset.position=player2.dataset.position;
				player2.dataset.position=temp1;
				game.arrangePlayers();
				if(player1.dataset.position=='0'||player2.dataset.position=='0'){
					pos=parseInt(player1.dataset.position);
					if(pos==0) pos=parseInt(player2.dataset.position);
					num=game.players.length+game.dead.length;
					for(i=0;i<game.players.length;i++){
						temp1=parseInt(game.players[i].dataset.position)-pos;
						if(temp1<0) temp1+=num;
						game.players[i].dataset.position=temp1;
					}
					for(i=0;i<game.dead.length;i++){
						temp1=parseInt(game.dead[i].dataset.position)-pos;
						if(temp1<0) temp1+=num;
						game.dead[i].dataset.position=temp1;
					}
				}
				game.playerMap={};
				var players=game.players.concat(game.dead);
				for(var i=0;i<players.length;i++){
					game.playerMap[players[i].dataset.position]=players[i];
				}
			},
			removeTafangPlayer:function(){
				ui.fakeme.hide();
				ui.handcards1Container.innerHTML='';
				ui.handcards2Container.innerHTML='';
				game.me=ui.create.player();
			},
			swapControl:function(player,hs){
				if(player&&player.node){
					var cards=get.infoCards(hs);
					player.node.handcards1.innerHTML='';
					player.node.handcards2.innerHTML='';
					player.directgain(cards,false);

					game.me.node.handcards1.remove();
					game.me.node.handcards2.remove();

					ui.handcards1=player.node.handcards1.animate('start').fix();
					ui.handcards2=player.node.handcards2.animate('start').fix();
					ui.handcards1Container.insertBefore(ui.handcards1,ui.handcards1Container.firstChild);
					ui.handcards2Container.insertBefore(ui.handcards2,ui.handcards2Container.firstChild);

					game.me=player;
					ui.updatehl();
					if(game.chess){
						ui.create.fakeme();
					}
				}
				else{
					console.log(player);
				}
			},
			onSwapControl:function(){
				game.onSwapControl();
			},
			swapPlayer:function(player,hs){
				if(player&&player.node){
					var cards=get.infoCards(hs);
					player.node.handcards1.innerHTML='';
					player.node.handcards2.innerHTML='';
					player.directgain(cards,false);

					var pos=parseInt(player.dataset.position);
					var num=game.players.length+game.dead.length;
					var players=game.players.concat(game.dead);
					var temp;
					for(var i=0;i<players.length;i++){
						temp=parseInt(players[i].dataset.position)-pos;
						if(temp<0) temp+=num;
						players[i].dataset.position=temp;
					}
					game.me.node.handcards1.remove();
					game.me.node.handcards2.remove();
					game.me=player;
					ui.handcards1=player.node.handcards1.animate('start').fix();
					ui.handcards2=player.node.handcards2.animate('start').fix();
					ui.handcards1Container.appendChild(ui.handcards1);
					ui.handcards2Container.appendChild(ui.handcards2);

					ui.updatehl();

					game.playerMap={};
					var players=game.players.concat(game.dead);
					for(var i=0;i<players.length;i++){
						game.playerMap[players[i].dataset.position]=players[i];
					}
				}
				else{
					console.log(player);
				}
			},
			over:function(str){
				var dialog=ui.create.dialog('hidden');
				dialog.noforcebutton=true;
				dialog.content.innerHTML=str;
				dialog.forcebutton=true;
				dialog.open();
				if(game.chess){
					dialog.classList.add('center');
				}
				if((game.layout=='long2'||game.layout=='nova')&&!game.chess){
					ui.arena.classList.add('choose-character');
					if(ui.me) ui.me.hide();
					if(ui.mebg) ui.mebg.hide()
					if(ui.autonode) ui.autonode.hide();
					if(lib.config.radius_size!='off'){
						if(ui.historybar) ui.historybar.style.borderRadius='0 0 0 4px';
					}
				}
			}
		},
		reload:function(){
			if(_status){
				if(_status.reloading) return;
				_status.reloading=true;
			}
			if(_status.video&&!_status.replayvideo){
				localStorage.removeItem(lib.configprefix+'playbackmode');
			}
			localStorage.setItem('show_splash_off',true);
			if(lib.status.reload){
				_status.waitingToReload=true;
			}
			else{
				window.location.reload();
			}
		},
		reload2:()=>{
			lib.status.reload--;
			if(lib.status.reload==0&&lib.ondb2.length){
				const command=lib.ondb2.shift();
				game[command[0]](...command[1]);
			}
			if(lib.status.reload==0&&lib.ondb.length){
				const command=lib.ondb.shift();
				game[command[0]](...command[1]);
			}
			if(lib.status.reload||!_status.waitingToReload) return;
			window.location.reload();
			delete _status.waitingToReload;
		},
		exit:function(){
			var ua=navigator.userAgent.toLowerCase();
			var ios=ua.includes('iphone')||ua.includes('ipad')||ua.includes('macintosh');
			//electron
			if(typeof window.process=='object'&&typeof window.require=='function'){
				var versions=window.process.versions;
				var electronVersion=parseFloat(versions.electron);
				var remote;
				if(electronVersion>=14){
					remote=require('@electron/remote');
				}else{
					remote=require('electron').remote;
				}
				var thisWindow=remote.getCurrentWindow();
				thisWindow.destroy();
				window.process.exit();
			}
			// android-cordova环境
			else if(lib.device==='android'){
				if(navigator.app&&navigator.app.exitApp){
					navigator.app.exitApp();
				}
			}
			//ios-cordova环境或ios浏览器环境
			else if(lib.device==='ios'||!lib.device&&ios){
				game.saveConfig('mode');
				if(_status){
					if(_status.reloading)return;
					_status.reloading=true;
				}
				if(_status.video&&!_status.replayvideo) {
					localStorage.removeItem(lib.configprefix+'playbackmode');
				}
				window.location.reload();
			}
			//非ios的网页版
			else if(!ios){
				window.onbeforeunload = null;
				window.close();
			}
		},
		open:function(url){
			if(lib.device){
				if(cordova.InAppBrowser){
					cordova.InAppBrowser.open(url,'_system');
				}
				else{
					ui.create.iframe(url);
				}
			}
			else{
				window.open(url);
			}
		},
		reloadCurrent:function(){
			game.saveConfig('continue_name',[game.me.name1||game.me.name,game.me.name2]);
			game.saveConfig('mode',lib.config.mode);
			localStorage.setItem(lib.configprefix+'directstart',true);
			game.reload();
		},
		update:function(func){
			lib.updates.push(func);
			if(lib.updates.length===1){
				game.run();
			}
			return func;
		},
		unupdate:function(func){
			lib.updates.remove(func);
		},
		stop:function(){
			cancelAnimationFrame(lib.status.frameId);
		},
		run:function(){
			if(lib.updates.length){
				cancelAnimationFrame(lib.status.frameId);
				lib.status.frameId=requestAnimationFrame(function(time){
					if(lib.status.time!==0){
						lib.status.delayed+=time-lib.status.time;
					}
					lib.status.frameId=requestAnimationFrame(lib.run);
				});
			}
		},
		addVideo:function(type,player,content){
			if(_status.video||game.online) return;
			if(!_status.videoInited){
				if(type=='arrangeLib'){
					lib.video.push({
						type:type,
						player:player,
						content:content,
						delay:0
					});
				}
				return;
			}
			if(type=='storage'&&player&&player.updateMarks){
				player.updateMarks();
			}
			if(game.getVideoName){
				var time=get.time();
				if(!_status.lastVideoLog){
					_status.lastVideoLog=time;
				}
				if(get.itemtype(player)=='player'){
					player=player.dataset.position;
				}
				lib.video.push({
					type:type,
					player:player,
					content:content,
					delay:time-_status.lastVideoLog
				});
				_status.lastVideoLog=time;
			}
		},
		draw:function(func){
			lib.canvasUpdates.push(func);
			if(!lib.status.canvas){
				lib.status.canvas=true;
				game.update(lib.updateCanvas);
			}
		},
		vibrate:function(time){
			if(typeof navigator.vibrate=='function'){
				navigator.vibrate(time||500);
			}
		},
		prompt:function(){
			var str,forced,callback,noinput=false,str2='';
			for(var i=0;i<arguments.length;i++){
				if(arguments[i]=='alert'){
					forced=true;
					callback=function(){};
					noinput=true;
				}
				else if(typeof arguments[i]=='string'){
					if(arguments[i].startsWith('###')){
						var list=arguments[i].slice(3).split('###');
						str=list[0];
						str2=list[1];
					}
					else str=arguments[i];
				}
				else if(typeof arguments[i]=='boolean'){
					forced=arguments[i];
				}
				else if(typeof arguments[i]=='function'){
					callback=arguments[i];
				}
			}
			if(!callback){
				return;
			}
			//try{
			//	if(noinput){
			//		throw('e');
			//	}
			//	var result=prompt(str);
			//	callback(result);
			//}
			//catch(e){
				var promptContainer=ui.create.div('.popup-container',ui.window,function(){
					if(this.clicked){
						this.clicked=false;
					}
					else{
						clickCancel();
					}
				});
				var dialogContainer=ui.create.div('.prompt-container',promptContainer);
				var dialog=ui.create.div('.menubg',ui.create.div(dialogContainer),function(){
					promptContainer.clicked=true;
				});
				var strnode=ui.create.div('',str||'',dialog);
				var input=ui.create.node('input',ui.create.div(dialog));
				input.value=str2;
				if(noinput){
					input.style.display='none';
				}
				var controls=ui.create.div(dialog);
				var clickConfirm=function(){
					if(noinput){
						promptContainer.remove();
					}
					else if(input.value){
						callback(input.value);
						promptContainer.remove();
					}
				}
				var clickCancel=function(){
					if(!forced){
						callback(false);
						promptContainer.remove();
					}
				}
				var confirmNode=ui.create.div('.menubutton.large.disabled','确定',controls,clickConfirm);
				if(!forced){
					ui.create.div('.menubutton.large','取消',controls,clickCancel);
				}
				if(noinput){
					confirmNode.classList.remove('disabled');
				}
				else{
					input.onkeydown=function(e){
						if(e.keyCode==13){
							clickConfirm();
						}
						else if(e.keyCode==27){
							clickCancel();
						}
					}
					input.onkeyup=function(){
						if(input.value){
							confirmNode.classList.remove('disabled');
						}
						else{
							confirmNode.classList.remove('disabled');
						}
					}
					input.focus();
				}
			//}
		},
		alert:function(str){
			game.prompt(str,'alert');
		},
		print:function(){
			if(!_status.toprint){
				_status.toprint=[];
			}
			_status.toprint.push(Array.from(arguments));
		},
		animate:{
			window:function(num){
				switch(num){
					case 1:{
						ui.window.style.transition='all 0.5s';
						ui.window.classList.add('zoomout3');
						ui.window.hide();
						game.addVideo('windowzoom1');
						game.delay(0,500);
						break;
					}
					case 2:{
						ui.window.style.transition='all 0s';
						ui.refresh(ui.window);
						game.addVideo('windowzoom2');
						game.pause();
						setTimeout(function(){
							ui.window.classList.remove('zoomout3');
							ui.window.classList.add('zoomin3');
							game.addVideo('windowzoom3');
							setTimeout(function(){
								ui.window.style.transition='all 0.5s';
								ui.refresh(ui.window);
								ui.window.show();
								ui.window.classList.remove('zoomin3');
								game.addVideo('windowzoom4');
								setTimeout(function(){
									ui.window.style.transition='';
									game.addVideo('windowzoom5');
									game.resume();
								},500);
							},100);
						},100);
						break;
					}
				}
			},
			flame:function(x,y,duration,type){
				var particles=[];
				var particle_count=50;
				if(type=='thunder'||type=='recover'){
					particle_count=30;
				}
				else if(type=='coin'||type=='dust'){
					particle_count=50;
				}
				else if(type=='legend'){
					particle_count=120;
				}
				else if(type=='epic'){
					particle_count=80;
				}
				else if(type=='rare'){
					particle_count=50;
				}
				for(var i = 0; i < particle_count; i++) {
					particles.push(new particle());
				}
				function particle() {
					this.speed = {x: -1+Math.random()*2, y: -5+Math.random()*5};
					if(type=='thunder'||type=='coin'||type=='dust'){
						this.speed.y=-3+Math.random()*5;
						this.speed.x=-2+Math.random()*4;
					}
					if(type=='legend'||type=='rare'||type=='epic'){
						this.speed.x*=3;
						this.speed.y*=1.5;
					}
					this.location = {x: x, y: y};

					this.radius = 0.5+Math.random()*1;

					this.life = 10+Math.random()*10;
					this.death = this.life;

					switch(type){
						case 'thunder':{
							this.b = 255;
							this.r = Math.round(Math.random()*255);
							this.g = Math.round(Math.random()*255);
							this.x+=Math.random()*20-10;
							this.y+=Math.random()*20-10;

							break;
						}
						case 'fire':{
							this.r = 255;
							this.g = Math.round(Math.random()*155);
							this.b = 0;
							break;
						}
						case 'coin':{
							this.r = 255;
							this.g = Math.round(Math.random()*25+230);
							this.b = Math.round(Math.random()*100+50);
							this.location.x+=Math.round(Math.random()*60)-30;
							this.location.y+=Math.round(Math.random()*40)-20;
							if(this.location.x<x){
								this.speed.x=-Math.abs(this.speed.x);
							}
							else if(this.location.x>x){
								this.speed.x=Math.abs(this.speed.x);
							}
							this.life*=1.3;
							this.death*=1.3;
							break;
						}
						case 'dust':{
							this.r = Math.round(Math.random()*55)+105;
							this.g = Math.round(Math.random()*55)+150;
							this.b = 255;
							this.location.x+=Math.round(Math.random()*60)-30;
							this.location.y+=Math.round(Math.random()*40)-20;
							if(this.location.x<x){
								this.speed.x=-Math.abs(this.speed.x);
							}
							else if(this.location.x>x){
								this.speed.x=Math.abs(this.speed.x);
							}
							this.life*=1.3;
							this.death*=1.3;
							break;
						}
						case 'legend':{
							this.r = 255;
							this.g = Math.round(Math.random()*100+155);
							this.b = Math.round(Math.random()*100+50);
							this.location.x+=Math.round(Math.random()*60)-30;
							this.location.y+=Math.round(Math.random()*40)-20;
							if(this.location.x<x){
								this.speed.x=-Math.abs(this.speed.x);
							}
							else if(this.location.x>x){
								this.speed.x=Math.abs(this.speed.x);
							}
							this.speed.x/=2;
							this.speed.y/=2;
							this.life*=2;
							this.death*=2;
							break;
						}
						case 'epic':{
							this.r = Math.round(Math.random()*55)+200;
							this.g = Math.round(Math.random()*100)+55;
							this.b = 255;
							this.location.x+=Math.round(Math.random()*60)-30;
							this.location.y+=Math.round(Math.random()*40)-20;
							if(this.location.x<x){
								this.speed.x=-Math.abs(this.speed.x);
							}
							else if(this.location.x>x){
								this.speed.x=Math.abs(this.speed.x);
							}
							this.speed.x/=2;
							this.speed.y/=2;
							this.life*=2;
							this.death*=2;
							break;
						}
						case 'rare':{
							this.r = Math.round(Math.random()*55)+105;
							this.g = Math.round(Math.random()*55)+150;
							this.b = 255;
							this.location.x+=Math.round(Math.random()*60)-30;
							this.location.y+=Math.round(Math.random()*40)-20;
							if(this.location.x<x){
								this.speed.x=-Math.abs(this.speed.x);
							}
							else if(this.location.x>x){
								this.speed.x=Math.abs(this.speed.x);
							}
							this.speed.x/=2;
							this.speed.y/=2;
							this.life*=2;
							this.death*=2;
							break;
						}
						case 'recover':{
							this.g = 255;
							this.r = Math.round(Math.random()*200+55);
							this.b = Math.round(Math.random()*155+55);
							this.location.x+=Math.round(Math.random()*60)-30;
							this.location.y+=Math.round(Math.random()*40)-20;
							if(this.location.x<x){
								this.speed.x=-Math.abs(this.speed.x);
							}
							else if(this.location.x>x){
								this.speed.x=Math.abs(this.speed.x);
							}
							this.speed.x/=2;
							this.speed.y/=2;
							this.life*=2;
							this.death*=2;
							break;
						}
						default:{
							this.r = 255;
							this.g = Math.round(Math.random()*155);
							this.b = 0;
						}
					}
				}

				game.draw(function(time,surface){
					surface.globalCompositeOperation = "source-over";
					surface.globalCompositeOperation = "lighter";

					for(var i = 0; i < particles.length; i++)
					{
						var p = particles[i];

						surface.beginPath();
						var middle=0.5;
						var radius=p.radius;
						if(type=='recover'||type=='legend'||type=='rare'||
							type=='epic'||type=='coin'||type=='dust'){
							middle=0.7;
							radius/=3;
						}

						p.opacity = Math.round(p.death/p.life*100)/100
						var gradient = surface.createRadialGradient(p.location.x, p.location.y, 0, p.location.x, p.location.y, p.radius);
						gradient.addColorStop(0, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")");
						gradient.addColorStop(middle, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")");
						gradient.addColorStop(1, "rgba("+p.r+", "+p.g+", "+p.b+", 0)");
						surface.fillStyle = gradient;
						surface.arc(p.location.x, p.location.y, radius, Math.PI*2, false);
						surface.fill();
						p.death--;
						if(type=='recover'){
							p.radius+=0.5;
						}
						else if(type=='coin'||type=='dust'){
							p.radius+=0.7;
						}
						else if(type=='legend'||type=='rare'||type=='epic'){
							p.radius+=0.5;
						}
						else {
							p.radius++;
						}
						p.location.x += (p.speed.x);
						p.location.y += (p.speed.y);

						if(p.death < 0 || p.radius < 0){
							if(typeof duration=='number'&&time+500>=duration){
								particles.splice(i--,1);
							}
							else{
								particles[i] = new particle();
							}
						}
					}
					if(particles.length==0){
						return false;
					}
				});
			}
		},
		linexy:function(path){
			const from=[path[0],path[1]],to=[path[2],path[3]];
			let total=typeof arguments[1]==='number'?arguments[1]:lib.config.duration*2,opacity=1,color=[255,255,255],dashed=false,drag=false;
			if(arguments[1]&&typeof arguments[1]=='object') Object.keys(arguments[1]).forEach(value=>{
				switch(value){
					case 'opacity':
						opacity=arguments[1][value];
						break;
					case 'color':
						color=arguments[1][value];
						break;
					case 'dashed':
						dashed=arguments[1][value];
						break;
					case 'duration':total=arguments[1][value];
				}
			});
			else if(typeof arguments[1]=='string') color=arguments[1];
			if(typeof color=='string') color=lib.lineColor.get(color)||[255,255,255];
			let node;
			if(arguments[1]=='drag'){
				color=[236,201,71];
				drag=true;
				if(arguments[2]) node=arguments[2];
				else{
					node=ui.create.div('.linexy.drag');
					node.style.left=`${from[0]}px`;
					node.style.top=`${from[1]}px`;
					node.style.background=`linear-gradient(transparent,rgba(${color.toString()},${opacity}),rgba(${color.toString()},${opacity}))`;
					if(game.chess) ui.chess.appendChild(node);
					else ui.arena.appendChild(node);
				}
			}
			else{
				node=ui.create.div('.linexy.hidden');
				node.style.left=`${from[0]}px`;
				node.style.top=`${from[1]}px`;
				node.style.background=`linear-gradient(transparent,rgba(${color.toString()},${opacity}),rgba(${color.toString()},${opacity}))`;
				node.style.transitionDuration=`${total/3000}s`;
			}
			const dy=to[1]-from[1],dx=to[0]-from[0];
			let deg=Math.atan(Math.abs(dy)/Math.abs(dx))/Math.PI*180;
			if(dx>=0) if(dy<=0) deg+=90;
			else deg=90-deg;
			else if(dy<=0) deg=270-deg;
			else deg+=270;
			if(drag){
				node.style.transform=`rotate(${(-deg)}deg)`;
				node.style.height=`${get.xyDistance(from,to)}px`;
			}
			else{
				node.style.transform=`rotate(${(-deg)}deg) scaleY(0)`;
				node.style.height=`${get.xyDistance(from,to)}px`;
				if(get.objtype(arguments[1])=='div') arguments[1].appendChild(node);
				else if(game.chess) ui.chess.appendChild(node);
				else ui.arena.appendChild(node);
				ui.refresh(node);
				node.show();
				node.style.transform=`rotate(${(-deg)}deg) scaleY(1)`;
				node.listenTransition(()=>setTimeout(()=>{
					if(!node.classList.contains('removing')) node.delete();
				},total/3));
			}
			return node;
		},
		_linexy:function(path){
			var from=[path[0],path[1]];
			var to=[path[2],path[3]];
			var total=typeof arguments[1]==='number'?arguments[1]:lib.config.duration*2;
			var opacity=1;
			var color=[255,255,255];
			var dashed=false;
			if(typeof arguments[1]=='object'){
				for(var i in arguments[1]){
					switch(i){
						case 'opacity':opacity=arguments[1][i];break;
						case 'color':color=arguments[1][i];break;
						case 'dashed':dashed=arguments[1][i];break;
						case 'duration':total=arguments[1][i];break;
					}
				}
			}
			else if(arguments[1]=='fire'||arguments[1]=='thunder'||arguments[1]=='green'){
				color=arguments[1];
			}
			if(color=='fire'){
				color=[255, 146, 68];
			}
			else if(color=='thunder'){
				color=[141, 216, 255];
			}
			else if(color=='green'){
				color=[141, 255, 216];
			}
			var drawfunc=function(time,ctx){
				var current;
				if(time<total/3){
					ctx.strokeStyle='rgba('+color.toString()+','+opacity*(time/(total/3))+')';
					current=[from[0]+(to[0]-from[0])*time/(total/3),
						from[1]+(to[1]-from[1])*time/(total/3)];
				}
				else if(time<=total){
					current=to;
					if(time>total/1.5){
						ctx.strokeStyle='rgba('+color.toString()+','+opacity*(1-(time-total/1.5)/(total-total/1.5))+')';
					}
					else{
						ctx.strokeStyle='rgba('+color.toString()+','+opacity+')';
					}
				}
				else{
					return false;
				}
				ctx.beginPath();
				if(dashed){
					ctx.lineCap='butt';
					ctx.setLineDash([8,2]);
				}
				else{
					ctx.lineCap='round';
				}
				ctx.moveTo(from[0],from[1]);
				ctx.lineTo(current[0],current[1]);
				ctx.stroke();
			};
			if(arguments[2]&&game.chess){
				game.draw2(drawfunc);
			}
			else{
				game.draw(drawfunc);
			}
		},
		createTrigger:function(name,skill,player,event){
			var info=get.info(skill);
			if(!info) return false;
			if((player.isOut()||player.removed)&&!info.forceOut) return;
			if(player.isDead()&&!info.forceDie) return;
			var next=game.createEvent('trigger',false);
			next.skill=skill;
			next.player=player;
			next.triggername=name;
			next.forceDie=true;
			next.includeOut=true;
			next._trigger=event;
			next.setContent('createTrigger');
		},
		createEvent:function(name,trigger,triggerevent){
			var next={
				name:name,
				step:0,
				finished:false,
				next:[],
				after:[],
				custom:{
					add:{},
					replace:{}
				},
				_aiexclude:[],
				_notrigger:[],
				_result:{},
				_set:[],
			}
			if(trigger!==false&&!game.online) next._triggered=0;
			for(var i in lib.element.event){
				next[i]=lib.element.event[i];
			}
			(triggerevent||_status.event).next.push(next);
			return next;
		},
		addCharacter:(name,information)=>{
			const extensionName=_status.extension||information.extension,character=[
				information.sex,
				information.group,
				information.hp,
				information.skills||[],
				[
					_status.evaluatingExtension?`db:extension-${extensionName}:${name}.jpg`:`ext:${extensionName}/${name}.jpg`,
					`die:ext:${extensionName}/${name}.mp3`
				]
			];
			if(information.tags) character[4]=character[4].concat(information.tags);
			lib.character[name]=character;
			const packName=`mode_extension_${extensionName}`;
			if(!lib.characterPack[packName]) lib.characterPack[packName]={};
			lib.translate[name]=information.translate;
			lib.characterPack[packName][name]=character;
			lib.translate[`${packName}_character_config`]=extensionName;
		},
		addCharacterPack:(pack,packagename)=>{
			var extname=_status.extension||'扩展';
			let gzFlag=false;
			packagename=packagename||extname;
			for(var i in pack){
				if(i=='mode'){
					if(pack[i]=="guozhan") gzFlag=true;
					continue;
				}
				if(i=='forbid') continue;
				for(var j in pack[i]){
					if(i=='character'){
						if(!pack[i][j][4]){
							pack[i][j][4]=[];
						}
						var imgsrc;
						if(_status.evaluatingExtension){
							imgsrc='db:extension-'+extname+':'+j+'.jpg';
						}
						else{
							imgsrc='ext:'+extname+'/'+j+'.jpg';
						}
						const audiosrc='die:ext:'+extname+'/'+j+'.mp3';
						if(!pack[i][j][4].some(str=>typeof str=="string"&&/^(?:db:extension-|ext:):(?:.+)/.test(str))) pack[i][j][4].add(imgsrc);
						if(!pack[i][j][4].some(str=>typeof str=="string"&&/^die:(?:.+)/.test(str))) pack[i][j][4].add(audiosrc);
						if(pack[i][j][4].contains('boss')||
							pack[i][j][4].contains('hiddenboss')){
							lib.config.forbidai.add(j);
						}
						if(lib.config.forbidai_user&&lib.config.forbidai_user.contains(j)){
							lib.config.forbidai.add(j);
						}
						for(var l=0;l<pack[i][j][3].length;l++){
							lib.skilllist.add(pack[i][j][3][l]);
						}
					}
					else if(i=='skill'){
						if(typeof pack[i][j].audio=='number'||typeof pack[i][j].audio=='boolean'){
							pack[i][j].audio='ext:'+extname+':'+pack[i][j].audio;
						}
					}
					if(lib[i][j]==undefined){
						lib[i][j]=pack[i][j];
					}
				}
			}
			var packname='mode_extension_'+packagename;
			lib.characterPack[packname]=pack.character;
			lib.translate[packname+'_character_config']=packagename;
			if(gzFlag) lib.characterGuozhanFilter.add(packname);
		},
		addCard:function(name,info,info2){
			var extname=(_status.extension||info2.extension);
			if(info.audio==true){
				info.audio='ext:'+extname;
			}
			if(info.fullskin){
				if(_status.evaluatingExtension){
					info.image='db:extension-'+extname+':'+name+'.png';
				}
				else{
					info.image='ext:'+extname+'/'+name+'.png';
				}
			}
			else if(info.fullimage){
				if(_status.evaluatingExtension){
					info.image='db:extension-'+extname+':'+name+'.jpg';
				}
				else{
					info.image='ext:'+extname+'/'+name+'.jpg';
				}
			}
			lib.card[name]=info;
			lib.translate[name]=info2.translate;
			lib.translate[name+'_info']=info2.description;
			if(typeof info2.number=='number'){
				var suits=['heart','spade','diamond','club'];
				if(info2.color=='red'){
					suits=['heart','diamond'];
				}
				else if(info2.color=='black'){
					suits=['club','spade'];
				}
				for(var i=0;i<info2.number;i++){
					lib.card.list.push([suits[Math.floor(Math.random()*suits.length)],Math.ceil(Math.random()*13),name]);
				}
			}
			var packname='mode_extension_'+extname;
			if(!lib.cardPack[packname]){
				lib.cardPack[packname]=[];
				lib.translate[packname+'_card_config']=extname;
			}
			lib.cardPack[packname].push(name);
		},
		addCardPack:function(pack,packagename){
			var extname=_status.extension||'扩展';
			packagename=packagename||extname;
			var packname='mode_extension_'+packagename;
			lib.cardPack[packname]=[];
			lib.translate[packname+'_card_config']=packagename;
			for(var i in pack){
				if(i=='mode'||i=='forbid') continue;
				if(i=='list'){
					for(var j=0;j<pack[i].length;j++){
						lib.card.list.push(pack[i][j]);
					}
					continue;
				}
				for(var j in pack[i]){
					if(i=='card'){
						if(pack[i][j].audio==true){
							pack[i][j].audio='ext:'+extname;
						}
						if(pack[i][j].fullskin){
							if(_status.evaluatingExtension){
								pack[i][j].image='db:extension-'+extname+':'+j+'.png';
							}
							else{
								pack[i][j].image='ext:'+extname+'/'+j+'.png';
							}
						}
						else if(pack[i][j].fullimage){
							if(_status.evaluatingExtension){
								pack[i][j].image='db:extension-'+extname+':'+j+'.jpg';
							}
							else{
								pack[i][j].image='ext:'+extname+'/'+j+'.jpg';
							}
						}
						lib.cardPack[packname].push(j);
					}
					else if(i=='skill'){
						if(typeof pack[i][j].audio=='number'||typeof pack[i][j].audio=='boolean'){
							pack[i][j].audio='ext:'+extname+':'+pack[i][j].audio;
						}
					}
					if(lib[i][j]==undefined) lib[i][j]=pack[i][j];
				}
			}
		},
		addSkill:function(name,info,translate,description,appendInfo){
			if(lib.skill[name]){
				return false;
			}
			if(typeof info.audio=='number'||typeof info.audio=='boolean'){
				info.audio='ext:'+_status.extension+':'+info.audio;
			}
			lib.skill[name]=info;
			lib.translate[name]=translate;
			lib.translate[name+'_info']=description;
			lib.translate[name+'_append']=appendInfo;
			return true;
		},
		addMode:function(name,info,info2){
			lib.config.all.mode.push(name);
			lib.translate[name]=info2.translate;
			var imgsrc;
			var extname=_status.extension||info2.extension;
			if(_status.evaluatingExtension){
				imgsrc='extension-'+extname+':'+name+'.jpg';
			}
			else{
				imgsrc='ext:'+extname+'/'+name+'.jpg';
			}
			lib.mode[name]={
				name:info2.translate,
				config:info2.config,
				splash:imgsrc,
				fromextension:true
			}
			lib.init['setMode_'+name]=gnc.of(function*(){
				yield game.import('mode',function(lib,game,ui,get,ai,_status){
					info.name=name;
					return info;
				});
			});
			if(!lib.config.extensionInfo[extname]){
				lib.config.extensionInfo[extname]={};
			}
			if(!lib.config.extensionInfo[extname].mode){
				lib.config.extensionInfo[extname].mode=[];
			}
			if(lib.config.extensionInfo[extname].mode.indexOf(name)==-1){
				lib.config.extensionInfo[extname].mode.push(name);
			}
			game.saveConfig('extensionMode',lib.config.extensionInfo);
		},
		addGlobalSkill:function(skill,player){
			var info=lib.skill[skill];
			if(!info) return false;
			lib.skill.global.add(skill);
			if(player){
				if(!lib.skill.globalmap[skill]){
					lib.skill.globalmap[skill]=[];
				}
				lib.skill.globalmap[skill].add(player);
			}
			if(info.trigger){
				var setTrigger=function(i,evt){
					var name=i+'_'+evt;
					if(!lib.hook.globalskill[name]){
						lib.hook.globalskill[name]=[];
					}
					lib.hook.globalskill[name].add(skill);
					lib.hookmap[evt]=true;
				}
				for(var i in info.trigger){
					if(typeof info.trigger[i]=='string'){
						setTrigger(i,info.trigger[i]);
					}
					else if(Array.isArray(info.trigger[i])){
						for(var j=0;j<info.trigger[i].length;j++){
							setTrigger(i,info.trigger[i][j]);
						}
					}
				}
			}
			return true;
		},
		removeGlobalSkill:function(skill){
			lib.skill.global.remove(skill);
			delete lib.skill.globalmap[skill];
			for(var i in lib.hook.globalskill){
				lib.hook.globalskill[i].remove(skill);
			}
		},
		resetSkills:function(){
			for(var i=0;i<game.players.length;i++){
				for(var j in game.players[i].tempSkills){
					game.players[i].removeSkill(j);
				}
				var skills=game.players[i].getSkills();
				for(var j=0;j<skills.length;j++){
					if(lib.skill[skills[j]].vanish){
						game.players[i].removeSkill(skills[j]);
					}
				}
				game.players[i].in(true);
			}
			ui.clear();
		},
		removeExtension:(extensionName,keepFile)=>{
			const prefix=`extension_${extensionName}`;
			Object.keys(lib.config).forEach(key=>{
				if(key.startsWith(prefix)) game.saveConfig(key);
			});
			localStorage.removeItem(`${lib.configprefix}${prefix}`);
			game.deleteDB('data',prefix);
			lib.config.extensions.remove(extensionName);
			game.saveConfig('extensions',lib.config.extensions);
			const modeList=lib.config.extensionInfo[extensionName];
			if(modeList){
				if(modeList.file) Object.values(modeList.file).forEach(filePath=>game.deleteDB('image',`extension-${extensionName}:${filePath}`));
				if(modeList.mode) Object.values(modeList.mode).forEach(game.clearModeConfig);
				delete lib.config.extensionInfo[extensionName];
				game.saveConfigValue('extensionInfo');
			}
			if(!game.download||keepFile) return;
			if(lib.node&&lib.node.fs) try{
				const deleteFolderRecursive=path=>{
					if(!lib.node.fs.existsSync(path)) return;
					lib.node.fs.readdirSync(path).forEach((file,index)=>{
						const currentPath = `${path}/${file}`;
						if (lib.node.fs.lstatSync(currentPath).isDirectory()) deleteFolderRecursive(currentPath);
						else lib.node.fs.unlinkSync(currentPath);
					});
					lib.node.fs.rmdirSync(path);
				};
				deleteFolderRecursive(`${__dirname}/extension/${extensionName}`);
			}
			catch(error){
				console.log(error);
			}
			else new Promise((resolve,reject)=>window.resolveLocalFileSystemURL(`${lib.assetURL}extension/${extensionName}`,resolve,reject)).then(directoryEntry=>directoryEntry.removeRecursively());
		},
		addRecentCharacter:function(){
			var list=get.config('recentCharacter')||[];
			for(var i=0;i<arguments.length;i++){
				if(lib.character[arguments[i]]){
					list.remove(arguments[i]);
					list.unshift(arguments[i]);
				}
			}
			var num=parseInt(lib.config.recent_character_number);
			if(list.length>num){
				list.splice(num);
			}
			game.saveConfig('recentCharacter',list,true);
		},
		createCard:function(name,suit,number,nature){
			if(typeof name=='object'){
				nature=name.nature;
				number=name.number;
				suit=name.suit;
				name=name.name;
			}
			if(typeof name!='string'){
				name='sha';
			}
			var noclick=false;
			if(suit=='noclick'){
				noclick=true;
				suit=null;
			}
			if(!suit&&lib.card[name].cardcolor){
				suit=lib.card[name].cardcolor;
			}
			if(!nature&&lib.card[name].cardnature){
				nature=lib.card[name].cardnature;
			}
			if(typeof suit!='string'){
				suit=['heart','diamond','club','spade'].randomGet();
			}
			else if(suit=='black'){
				suit=Math.random()<0.5?'club':'spade';
			}
			else if(suit=='red'){
				suit=Math.random()<0.5?'diamond':'heart';
			}
			if(typeof number!='number'&&typeof number!='string'){
				number=Math.ceil(Math.random()*13);
			}
			var card;
			if(noclick){
				card=ui.create.card(ui.special,'noclick',true);
			}
			else{
				card=ui.create.card(ui.special);
			}
			card.storage.vanish=true;
			return card.init([suit,number,name,nature]);
		},
		createCard2:function(){
			var card=game.createCard.apply(this,arguments);
			delete card.storage.vanish;
			return card;
		},
		forceOver:function(bool,callback){
			_status.event.next.length=0;
			var next=game.createEvent('finish_game');
			next.bool=bool;
			next.callback=callback;
			next.setContent('forceOver');
			if(_status.paused){
				game.uncheck();
				game.resume();
			}
		},
		over:function(result){
			if(_status.over) return;
			if(game.me._trueMe) game.swapPlayer(game.me._trueMe);
			var i,j,k,num,table,tr,td,dialog;
			_status.over=true;
			ui.control.show();
			ui.clear();
			game.stopCountChoose();
			if(ui.time3){
				clearInterval(ui.time3.interval);
			}
			if((game.layout=='long2'||game.layout=='nova')&&!game.chess){
				ui.arena.classList.add('choose-character');
				ui.me.hide();
				ui.mebg.hide()
				ui.autonode.hide();
				if(lib.config.radius_size!='off'){
					ui.historybar.style.borderRadius='0 0 0 4px';
				}
			}
			if(game.online){
				var dialog=ui.create.dialog();
				dialog.noforcebutton=true;
				dialog.content.innerHTML=result;
				dialog.forcebutton=true;
				var result2=arguments[1];
				if(result2==true){
					dialog.content.firstChild.innerHTML='战斗胜利';
				}
				else if(result2==false){
					dialog.content.firstChild.innerHTML='战斗失败';
				}
				ui.update();
				dialog.add(ui.create.div('.placeholder'));
				for(var i=0;i<game.players.length;i++){
					var hs=game.players[i].getCards('h');
					if(hs.length){
						dialog.add('<div class="text center">'+get.translation(game.players[i])+'</div>');
						dialog.addSmall(hs);
					}
				}
				
				for(var j=0;j<game.dead.length;j++){
					var hs=game.dead[j].getCards('h');
					if(hs.length){
						dialog.add('<div class="text center">'+get.translation(game.dead[j])+'</div>');
						dialog.addSmall(hs);
					}
				}
				
				dialog.add(ui.create.div('.placeholder.slim'));
				if(lib.config.background_audio){
					if(result2===true){
						game.playAudio('effect','win');
					}
					else if(result2===false){
						game.playAudio('effect','lose');
					}
					else{
						game.playAudio('effect','tie');
					}
				}
				if(!ui.exit){
					ui.create.exit();
				}
				if(ui.giveup){
					ui.giveup.remove();
					delete ui.giveup;
				}
				if(game.servermode){
					ui.exit.firstChild.innerHTML='返回房间';
					setTimeout(function(){
						ui.exit.firstChild.innerHTML='退出房间';
						_status.roomtimeout=true;
						lib.config.reconnect_info[2]=null;
						game.saveConfig('reconnect_info',lib.config.reconnect_info);
					},10000);
				}
				if(ui.tempnowuxie){
					ui.tempnowuxie.close();
					delete ui.tempnowuxie;
				}
				if(ui.auto) ui.auto.hide();
				if(ui.wuxie) ui.wuxie.hide();
				if(game.getIdentityList){
					for(var i=0;i<game.players.length;i++){
						game.players[i].setIdentity();
					}
				}
				return;
			}
			if(lib.config.background_audio){
				if(result===true){
					game.playAudio('effect','win');
				}
				else if(result===false){
					game.playAudio('effect','lose');
				}
				else{
					game.playAudio('effect','tie');
				}
			}
			var resultbool=result;
			if(typeof resultbool!=='boolean'){
				resultbool=null;
			}
			if(result===true) result='战斗胜利';
			if(result===false) result='战斗失败';
			if(result==undefined) result='战斗结束';
			dialog=ui.create.dialog(result);
			dialog.noforcebutton=true;
			dialog.forcebutton=true;
			if(game.addOverDialog){
				game.addOverDialog(dialog,result);
			}
			if(typeof _status.coin=='number'&&!_status.connectMode){
				var coeff=Math.random()*0.4+0.8;
				var added=0;
				var betWin=false;
				if(result=='战斗胜利'){
					if(_status.betWin){
						betWin=true;
						_status.coin+=10;
					}
					_status.coin+=20;
					if(_status.additionalReward){
						_status.coin+=_status.additionalReward();
					}
					switch(lib.config.mode){
						case 'identity':{
							switch(game.me.identity){
								case 'zhu':case 'zhong':case 'mingzhong':
									if(get.config('enhance_zhu')){
										added=10;
									}
									else{
										added=20;
									}
									break;
								case 'fan':
									if(get.config('enhance_zhu')){
										added=16;
									}
									else{
										added=8;
									}
									break;
								case 'nei':
									added=40;
									break;
							}
							added=added*(game.players.length+game.dead.length)/8;
							break;
						}
						case 'guozhan':
							if(game.me.identity=='ye'){
								added=8;
							}
							else{
								added=5/get.totalPopulation(game.me.identity);
							}
							added=added*(game.players.length+game.dead.length);
							break;
						case 'versus':
							if(_status.friend){
								added=5*(game.players.length+_status.friend.length);
							}
							break;
						default:
							added=10;
					}
				}
				else{
					added=10;
				}
				if(lib.config.mode=='chess'&&_status.mode=='combat'&&get.config('additional_player')){
					added=2;
				}
				_status.coin+=added*coeff;
				if(_status.coinCoeff){
					_status.coin*=_status.coinCoeff;
				}
				_status.coin=Math.ceil(_status.coin);
				dialog.add(ui.create.div('','获得'+_status.coin+'金'));
				if(betWin){
					game.changeCoin(20);
					dialog.content.appendChild(document.createElement('br'));
					dialog.add(ui.create.div('','(下注赢得10金)'));
				}
				game.changeCoin(_status.coin);
			}
			if(get.mode()=='versus'&&_status.ladder){
				var mmr=_status.ladder_mmr;
				mmr+=10-get.rank(game.me.name,true)*2;
				if(result=='战斗胜利'){
					mmr=20+Math.round(mmr);
					if(mmr>40){
						mmr=40;
					}
					else if(mmr<10){
						mmr=10;
					}
					dialog.add(ui.create.div('','获得 '+mmr+' 积分'));
				}
				else{
					mmr=-30+Math.round(mmr/2);
					if(mmr>-20){
						mmr=-20;
					}
					else if(mmr<-35){
						mmr=-35;
					}
					if(lib.storage.ladder.current<900){
						mmr=Math.round(mmr/4);
					}
					else if(lib.storage.ladder.current<1400){
						mmr=Math.round(mmr/2);
					}
					else if(lib.storage.ladder.current<2000){
						mmr=Math.round(mmr/1.5);
					}
					else if(lib.storage.ladder.current>2500){
						mmr=Math.round(mmr*1.5);
					}
					dialog.add(ui.create.div('','失去 '+(-mmr)+' 积分'));
				}
				if(_status.ladder_tmp){
					lib.storage.ladder.current+=40;
					delete _status.ladder_tmp;
				}
				lib.storage.ladder.current+=mmr;
				if(lib.storage.ladder.top<lib.storage.ladder.current){
					lib.storage.ladder.top=lib.storage.ladder.current;
				}
				game.save('ladder',lib.storage.ladder);
				if(ui.ladder&&game.getLadderName){
					ui.ladder.innerHTML=game.getLadderName(lib.storage.ladder.current);
				}
			}
			// if(true){
				if(game.players.length){
					table=document.createElement('table');
					tr=document.createElement('tr');
					tr.appendChild(document.createElement('td'));
					td=document.createElement('td');
					td.innerHTML='伤害';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='受伤';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='摸牌';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='出牌';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='杀敌';
					tr.appendChild(td);
					table.appendChild(tr);
					for(i=0;i<game.players.length;i++){
						tr=document.createElement('tr');
						td=document.createElement('td');
						td.innerHTML=get.translation(game.players[i]);
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.players[i].stat.length;j++){
							if(game.players[i].stat[j].damage!=undefined) num+=game.players[i].stat[j].damage;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.players[i].stat.length;j++){
							if(game.players[i].stat[j].damaged!=undefined) num+=game.players[i].stat[j].damaged;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.players[i].stat.length;j++){
							if(game.players[i].stat[j].gain!=undefined) num+=game.players[i].stat[j].gain;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.players[i].stat.length;j++){
							for(k in game.players[i].stat[j].card){
								num+=game.players[i].stat[j].card[k];
							}
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.players[i].stat.length;j++){
							if(game.players[i].stat[j].kill!=undefined) num+=game.players[i].stat[j].kill;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						table.appendChild(tr);
					}
					dialog.add(ui.create.div('.placeholder'));
					dialog.content.appendChild(table);
				}
				if(game.dead.length){
					table=document.createElement('table');
					table.style.opacity='0.5';
					if(game.players.length==0){
						tr=document.createElement('tr');
						tr.appendChild(document.createElement('td'));
						td=document.createElement('td');
						td.innerHTML='伤害';
						tr.appendChild(td);
						td=document.createElement('td');
						td.innerHTML='受伤';
						tr.appendChild(td);
						td=document.createElement('td');
						td.innerHTML='摸牌';
						tr.appendChild(td);
						td=document.createElement('td');
						td.innerHTML='出牌';
						tr.appendChild(td);
						td=document.createElement('td');
						td.innerHTML='杀敌';
						tr.appendChild(td);
						table.appendChild(tr);
					}
					for(i=0;i<game.dead.length;i++){
						tr=document.createElement('tr');
						td=document.createElement('td');
						td.innerHTML=get.translation(game.dead[i]);
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.dead[i].stat.length;j++){
							if(game.dead[i].stat[j].damage!=undefined) num+=game.dead[i].stat[j].damage;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.dead[i].stat.length;j++){
							if(game.dead[i].stat[j].damaged!=undefined) num+=game.dead[i].stat[j].damaged;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.dead[i].stat.length;j++){
							if(game.dead[i].stat[j].gain!=undefined) num+=game.dead[i].stat[j].gain;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.dead[i].stat.length;j++){
							for(k in game.dead[i].stat[j].card){
								num+=game.dead[i].stat[j].card[k];
							}
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.dead[i].stat.length;j++){
							if(game.dead[i].stat[j].kill!=undefined) num+=game.dead[i].stat[j].kill;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						table.appendChild(tr);
					}
					dialog.add(ui.create.div('.placeholder'));
					dialog.content.appendChild(table);
				}
				if(game.additionaldead&&game.additionaldead.length){
					table=document.createElement('table');
					table.style.opacity='0.5';
					for(i=0;i<game.additionaldead.length;i++){
						tr=document.createElement('tr');
						td=document.createElement('td');
						td.innerHTML=get.translation(game.additionaldead[i]);
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.additionaldead[i].stat.length;j++){
							if(game.additionaldead[i].stat[j].damage!=undefined) num+=game.additionaldead[i].stat[j].damage;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.additionaldead[i].stat.length;j++){
							if(game.additionaldead[i].stat[j].damaged!=undefined) num+=game.additionaldead[i].stat[j].damaged;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.additionaldead[i].stat.length;j++){
							if(game.additionaldead[i].stat[j].gain!=undefined) num+=game.additionaldead[i].stat[j].gain;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.additionaldead[i].stat.length;j++){
							for(k in game.additionaldead[i].stat[j].card){
								num+=game.additionaldead[i].stat[j].card[k];
							}
						}
						td.innerHTML=num;
						tr.appendChild(td);
						td=document.createElement('td');
						num=0;
						for(j=0;j<game.additionaldead[i].stat.length;j++){
							if(game.additionaldead[i].stat[j].kill!=undefined) num+=game.additionaldead[i].stat[j].kill;
						}
						td.innerHTML=num;
						tr.appendChild(td);
						table.appendChild(tr);
					}
					dialog.add(ui.create.div('.placeholder'));
					dialog.content.appendChild(table);
				}
			// }
			dialog.add(ui.create.div('.placeholder'));

			var clients=game.players.concat(game.dead);
			for(var i=0;i<clients.length;i++){
				if(clients[i].isOnline2()){
					clients[i].send(game.over,dialog.content.innerHTML,game.checkOnlineResult(clients[i]));
				}
			}

			dialog.add(ui.create.div('.placeholder'));

			for(var i=0;i<game.players.length;i++){
				if(!_status.connectMode&&game.players[i].isUnderControl(true)&&game.layout!='long2') continue;
				var hs=game.players[i].getCards('h');
				if(hs.length){
					dialog.add('<div class="text center">'+get.translation(game.players[i])+'</div>');
					dialog.addSmall(hs);
				}
			}
			for(var i=0;i<game.dead.length;i++){
				if(!_status.connectMode&&game.dead[i].isUnderControl(true)&&game.layout!='long2') continue;
				var hs=game.dead[i].getCards('h');
				if(hs.length){
					dialog.add('<div class="text center">'+get.translation(game.dead[i])+'</div>');
					dialog.addSmall(hs);
				}
			}
			dialog.add(ui.create.div('.placeholder.slim'));
			game.addVideo('over',null,dialog.content.innerHTML);
			var vinum=parseInt(lib.config.video);
			if(!_status.video&&vinum&&game.getVideoName&&window.indexedDB&&_status.videoInited){
				var store=lib.db.transaction(['video'],'readwrite').objectStore('video');
				var videos=lib.videos.slice(0);
				for(var i=0;i<videos.length;i++){
					if(videos[i].starred){
						videos.splice(i--,1);
					}
				}
				for(var deletei=0;deletei<5;deletei++){
					if(videos.length>=vinum){
						var toremove=videos.pop();
						lib.videos.remove(toremove);
						store.delete(toremove.time);
					}
					else{
						break;
					}
				}
				var me=game.me||game.players[0];
				if(!me) return;
				var newvid={
					name:game.getVideoName(),
					mode:lib.config.mode,
					video:lib.video,
					win:result=='战斗胜利',
					name1:me.name1||me.name,
					name2:me.name2,
					time:lib.getUTC(new Date())
				};
				var modecharacters=lib.characterPack['mode_'+get.mode()];
				if(modecharacters){
					if(get.mode()=='guozhan'){
						if(modecharacters[newvid.name1]){
							if(newvid.name1.startsWith('gz_shibing')){
								newvid.name1=newvid.name1.slice(3,11);
							}
							else{
								newvid.name1=newvid.name1.slice(3);
							}
						}
						if(modecharacters[newvid.name2]){
							if(newvid.name2.startsWith('gz_shibing')){
								newvid.name2=newvid.name2.slice(3,11);
							}
							else{
								newvid.name2=newvid.name2.slice(3);
							}
						}
					}
					else{
						if(modecharacters[newvid.name1]){
							newvid.name1=get.mode()+'::'+newvid.name1;
						}
						if(modecharacters[newvid.name2]){
							newvid.name2=get.mode()+'::'+newvid.name2;
						}
					}
				}
				if(newvid.name1&&newvid.name1.startsWith('subplayer_')){
					newvid.name1=newvid.name1.slice(10,newvid.name1.lastIndexOf('_'));
				}
				if(newvid.name2&&newvid.name2.startsWith('subplayer_')){
					newvid.name1=newvid.name2.slice(10,newvid.name1.lastIndexOf('_'));
				}
				lib.videos.unshift(newvid);
				store.put(newvid);
				ui.create.videoNode(newvid,true);
			}
			// _status.auto=false;
			if(ui.auto){
				// ui.auto.classList.remove('glow');
				ui.auto.hide();
			}
			if(ui.wuxie) ui.wuxie.hide();
			if(ui.giveup){
				ui.giveup.remove();
				delete ui.giveup;
			}

			if(lib.config.test_game&&!_status.connectMode){
				if(typeof lib.config.test_game!=='string'){ 
					switch(lib.config.mode){
						case 'identity':game.saveConfig('mode','guozhan');break;
						case 'guozhan':game.saveConfig('mode','versus');break;
						case 'versus':game.saveConfig('mode','boss');break;
						case 'boss':game.saveConfig('mode','chess');break;
						case 'chess':game.saveConfig('mode','stone');break;
						case 'stone':game.saveConfig('mode','identity');break;
					}
				}
				setTimeout(game.reload,500);
			}
			if(game.controlOver){
				game.controlOver();return;
			}
			if(!_status.brawl){
				if(lib.config.mode=='boss'){
					ui.create.control('再战',function(){
						var pointer=game.boss;
						var map={boss:game.me==game.boss,links:[]};
						for(var iwhile=0;iwhile<10;iwhile++){
							pointer=pointer.nextSeat;
							if(pointer==game.boss){
								break;
							}
							if(!pointer.side){
								map.links.push(pointer.name);
							}
						}
						game.saveConfig('continue_name_boss',map);
						game.saveConfig('mode',lib.config.mode);
						localStorage.setItem(lib.configprefix+'directstart',true);
						game.reload();
					});
				}
				else if(lib.config.mode=='versus'){
					if(_status.mode=='standard'||_status.mode=='three'){
						ui.create.control('再战',function(){
							game.saveConfig('continue_name_versus'+(_status.mode=='three'?'_three':''),{
								friend:_status.friendBackup,
								enemy:_status.enemyBackup,
								color:_status.color
							});
							game.saveConfig('mode',lib.config.mode);
							localStorage.setItem(lib.configprefix+'directstart',true);
							game.reload();
						});
					}
				}
				else if(!_status.connectMode&&get.config('continue_game')&&!ui.continue_game&&!_status.brawl&&!game.no_continue_game){
					ui.continue_game=ui.create.control('再战',game.reloadCurrent);
				}
			}
			if(!ui.restart){
				if(game.onlineroom&&typeof game.roomId=='string'){
					ui.restart=ui.create.control('restart',function(){
						game.broadcastAll(function(){
							if(ui.exit){
								ui.exit.stay=true;
								ui.exit.firstChild.innerHTML='返回房间';
							}
						});
						game.saveConfig('tmp_owner_roomId',game.roomId);
						setTimeout(game.reload,100);
					});
				}
				else{
					ui.restart=ui.create.control('restart',game.reload);
				}
			}
			if(ui.tempnowuxie){
				ui.tempnowuxie.close();
				delete ui.tempnowuxie;
			}

			if(ui.revive){
				ui.revive.close();
				delete ui.revive;
			}
			if(ui.swap){
				ui.swap.close();
				delete ui.swap;
			}
			for(var i=0;i<lib.onover.length;i++){
				lib.onover[i](resultbool);
			}
			if(game.addRecord){
				game.addRecord(resultbool);
			}
			if(window.isNonameServer){
				lib.configOL.gameStarted=false;
				game.saveConfig('pagecfg'+window.isNonameServer,[lib.configOL,game.roomId,_status.onlinenickname,_status.onlineavatar]);
				game.reload();
			}
			else if(_status.connectMode&&!game.online){
				setTimeout(game.reload,15000)
			}
		},
		loop:function(){
			while(true){
				var event=_status.event;
				var step=event.step;
				var source=event.source;
				var player=event.player;
				var target=event.target;
				var targets=event.targets;
				var card=event.card;
				var cards=event.cards;
				var skill=event.skill;
				var forced=event.forced;
				var num=event.num;
				var trigger=event._trigger;
				var result=event._result;
				if(_status.paused2||_status.imchoosing){
					if(!lib.status.dateDelaying){
						lib.status.dateDelaying=new Date();
					}
				}
				if(_status.paused||_status.paused2||_status.over){
					return;
				}
				if(_status.paused3){
					_status.paused3='paused';
					return;
				}
				if(lib.status.dateDelaying){
					lib.status.dateDelayed+=lib.getUTC(new Date())-lib.getUTC(lib.status.dateDelaying);
					delete lib.status.dateDelaying;
				}
				if(event.next.length>0){
					var next=event.next.shift();
					if(next.player&&next.player.skipList.contains(next.name)){
						event.trigger(next.name+'Skipped');
						next.player.skipList.remove(next.name);
						if(lib.phaseName.contains(next.name)) next.player.getHistory('skipped').add(next.name);
					}
					else{
						next.parent=event;
						_status.event=next;
						game.getGlobalHistory('everything').push(next);
					}
				}
				else if(event.finished){
					if(event._triggered==1){
						if(event.type=='card') event.trigger('useCardToOmitted');
						event.trigger(event.name+'Omitted');
						event._triggered=4;
					}
					else if(event._triggered==2){
						if(event.type=='card') event.trigger('useCardToEnd');
						event.trigger(event.name+'End');
						event._triggered=3;
					}
					else if(event._triggered==3){
						if(event.type=='card') event.trigger('useCardToAfter');
						event.trigger(event.name+'After');
						event._triggered++;
					}
					else if(event.after&&event.after.length){
						var next=event.after.shift();
						if(next.player&&next.player.skipList.contains(next.name)){
							event.trigger(next.name+'Skipped');
							next.player.skipList.remove(next.name);
							if(lib.phaseName.contains(next.name)) next.player.getHistory('skipped').add(next.name)
						}
						else{
							next.parent=event;
							_status.event=next;
						}
					}
					else{
						if(event.parent){
							if(event.result){
								event.parent._result=event.result;
							}
							_status.event=event.parent;
						}
						else{
							return;
						}
					}
				}
				else{
					if(event._triggered==0){
						if(event.type=='card') event.trigger('useCardToBefore');
						event.trigger(event.name+'Before');
						event._triggered++;
					}
					else if(event._triggered==1){
						if(event.type=='card') event.trigger('useCardToBegin');
						event.trigger(event.name+'Begin');
						event._triggered++;
						/*if(event.name=='phase'&&!event._begun){
							var next=game.createEvent('phasing',false,event);
							next.player=event.player;
							next.skill=event.skill;
							next.setContent('phasing');
							event._begun=true;
						}
						else{
							event.trigger(event.name+'Begin');
							event._triggered++;
						}*/
					}
					else{
						if(player&&player.classList.contains('dead')&&!event.forceDie&&event.name!='phaseLoop'){
							game.broadcastAll(function(){
								while(_status.dieClose.length){
									_status.dieClose.shift().close();
								}
							});
							if(event._oncancel){
								event._oncancel();
							}
							event.finish();
						}
						else if(player&&player.removed&&event.name!='phaseLoop'){
							event.finish();
						}
						else if(player&&player.isOut()&&event.name!='phaseLoop'&&!event.includeOut){
							if(event.name=='phase'&&player==_status.roundStart&&!event.skill){
								_status.roundSkipped=true;
							}
							event.finish();
						}
						else{
							if(_status.withError||lib.config.compatiblemode||(_status.connectMode&&!lib.config.debug)){
								try{
									event.content(event,step,source,player,target,targets,
										card,cards,skill,forced,num,trigger,result,
										_status,lib,game,ui,get,ai);
								}
								catch(e){
									game.print('游戏出错:'+event.name);
									game.print(e.toString());
									console.log(e);
								}
							}
							else{
								event.content(event,step,source,player,target,targets,
									card,cards,skill,forced,num,trigger,result,
									_status,lib,game,ui,get,ai);
							}
						}
						event.clearStepCache();
						event.step++;
					}
				}
			}
		},
		pause:function(){
			clearTimeout(_status.timeout);
			_status.paused=true;
		},
		pause2:function(){
			if(_status.connectMode) return;
			_status.paused2=true;
		},
		resume:function(){
			if(_status.paused){
				if(!_status.noclearcountdown){
					game.stopCountChoose();
				}
				_status.paused=false;
				delete _status.waitingForTransition;
				game.loop();
			}
		},
		resume2:function(){
			if(_status.connectMode) return;
			if(_status.paused2){
				_status.paused2=false;
				game.loop();
			}
		},
		delaye:function(){
			var next=game.createEvent('delay',false);
			next.setContent('delay');
			next._args=Array.from(arguments);
			return next;
		},
		delayex:function(){
			var next=game.createEvent('delayx',false);
			next.setContent('delay');
			next._args=Array.from(arguments);
			return next;
		},
		delay:function(time,time2){
			if(_status.paused) return;
			game.pause();
			if(typeof time!='number') time=1;
			if(typeof time2!='number') time2=0;
			time=time*lib.config.duration+time2;
			if(lib.config.speed=='vvfast') time/=3;
			_status.timeout=setTimeout(game.resume,time);
		},
		delayx:function(time,time2){
			if(typeof time!='number') time=1;
			switch(lib.config.game_speed){
				case 'vslow':time*=2.5;break;
				case 'slow':time*=1.5;break;
				case 'fast':time*=0.7;break;
				case 'vfast':time*=0.4;break;
				case 'vvfast':time*=0.2;break;
			}
			return game.delay(time,time2);
		},
		check:function(event){
			var i,j,range;
			if(event==undefined) event=_status.event;
			event._checked=true;
			var custom=event.custom||{};
			var ok=true,auto=true;
			var player=event.player;
			var auto_confirm=lib.config.auto_confirm;
			var players=game.players.slice(0);
			if(event.deadTarget) players.addArray(game.dead);
			if(!event.filterButton&&!event.filterCard&&!event.filterTarget&&(!event.skill||!event._backup)){
				if(event.choosing){
					_status.imchoosing=true;
				}
				return;
			}
			player.node.equips.classList.remove('popequip');
			if(event.filterButton){
				var dialog=event.dialog;
				range=get.select(event.selectButton);
				var selectableButtons=false;
				if(event.forceAuto&&ui.selected.buttons.length==range[1]) auto=true;
				else if(range[0]!=range[1]||range[0]>1) auto=false;
				for(i=0;i<dialog.buttons.length;i++){
					if(dialog.buttons[i].classList.contains('unselectable')) continue;
					if(event.filterButton(dialog.buttons[i],player)&&lib.filter.buttonIncluded(dialog.buttons[i])){
						if(ui.selected.buttons.length<range[1]){
							dialog.buttons[i].classList.add('selectable');
						}
						else if(range[1]<=-1){
							dialog.buttons[i].classList.add('selected');
							ui.selected.buttons.add(dialog.buttons[i]);
						}
						else{
							dialog.buttons[i].classList.remove('selectable');
						}
					}
					else{
						dialog.buttons[i].classList.remove('selectable');
						if(range[1]<=-1){
							dialog.buttons[i].classList.remove('selected');
							ui.selected.buttons.remove(dialog.buttons[i]);
						}
					}
					if(dialog.buttons[i].classList.contains('selected')){
						dialog.buttons[i].classList.add('selectable');
					}
					else if(!selectableButtons&&dialog.buttons[i].classList.contains('selectable')){
						selectableButtons=true;
					}
				}
				if(ui.selected.buttons.length<range[0]){
					if(!event.forced||selectableButtons){
						ok=false;
					}
					if(event.complexSelect||event.getParent().name=='chooseCharacter'||event.getParent().name=='chooseButtonOL'){
						ok=false;
					}
				}
				if(custom.add.button){
					custom.add.button();
				}
			}
			if(event.filterCard){
				if(ok==false){
					game.uncheck('card');
				}
				else{
					var cards=player.getCards(event.position);
					var firstCheck=false;
					range=get.select(event.selectCard);
					if(!event._cardChoice&&typeof event.selectCard!='function'&&
						!event.complexCard&&range[1]>-1&&!lib.config.compatiblemode){
						event._cardChoice=[];
						firstCheck=true;
					}
					if(event.isMine()&&event.name=='chooseToUse'&&event.parent.name=='phaseUse'&&!event.skill&&
						!event._targetChoice&&!firstCheck&&window.Map&&!lib.config.compatiblemode){
						event._targetChoice=new Map();
						for(var i=0;i<event._cardChoice.length;i++){
							if(!lib.card[event._cardChoice[i].name].complexTarget){
								var targets=[];
								for(var j=0;j<players.length;j++){
									if(event.filterTarget(event._cardChoice[i],player,players[j])){
										targets.push(players[j]);
									}
								}
								event._targetChoice.set(event._cardChoice[i],targets);
							}
						}
					}
					var selectableCards=false;
					if(range[0]!=range[1]||range[0]>1) auto=false;
					for(i=0;i<cards.length;i++){
						if(lib.config.cardtempname!='off'){
							var cardname=get.name(cards[i]);
							if(cards[i].name!=cardname||!get.is.sameNature(get.nature(cards[i]),cards[i].nature,true)){
								var node=ui.create.cardTempName(cards[i]);
								var cardtempnameConfig=lib.config.cardtempname;
								if(cardtempnameConfig!=='default') node.classList.remove('vertical');
							}
						}
						var nochess=true;
						if(!lib.filter.cardAiIncluded(cards[i])){
							nochess=false;
						}
						else if(event._cardChoice&&!firstCheck){
							if(!event._cardChoice.contains(cards[i])){
								nochess=false;
							}
						}
						else{
							if(player.isOut()||!lib.filter.cardRespondable(cards[i],player)||
							cards[i].classList.contains('uncheck')||
							!event.filterCard(cards[i],player)){
								nochess=false;
							}
						}
						if(nochess){
							if(ui.selected.cards.length<range[1]){
								cards[i].classList.add('selectable');
								if(event._cardChoice&&firstCheck){
									event._cardChoice.push(cards[i]);
								}
							}
							else if(range[1]<=-1){
								cards[i].classList.add('selected');
								cards[i].updateTransform(true);
								ui.selected.cards.add(cards[i]);
							}
							else{
								cards[i].classList.remove('selectable');
							}
						}
						else{
							cards[i].classList.remove('selectable');
							if(range[1]<=-1){
								cards[i].classList.remove('selected');
								cards[i].updateTransform();
								ui.selected.cards.remove(cards[i]);
							}
						}
						if(cards[i].classList.contains('selected')){
							cards[i].classList.add('selectable');
						}
						else if(!selectableCards&&cards[i].classList.contains('selectable')){
							selectableCards=true;
						}
					}
					if(ui.selected.cards.length<range[0]){
						if(!event.forced||selectableCards||event.complexSelect){
							ok=false;
						}
					}

					if(lib.config.popequip&&get.is.phoneLayout()&&
						typeof event.position=='string'&&event.position.includes('e')&&
						player.node.equips.querySelector('.card.selectable')){
						player.node.equips.classList.add('popequip');
						auto_confirm=false;
					}
				}
				if(custom.add.card){
					custom.add.card();
				}
			}
			if(event.filterTarget){
				if(ok==false){
					game.uncheck('target');
				}
				else{
					var card=get.card();
					var firstCheck=false;
					range=get.select(event.selectTarget);
					var selectableTargets=false;
					if(range[0]!=range[1]||range[0]>1) auto=false;
					for(i=0;i<players.length;i++){
						var nochess=true;
						if(game.chess&&!event.chessForceAll&&player&&get.distance(player,players[i],'pure')>7){
							nochess=false;
						}
						else if(players[i].isOut()){
							nochess=false;
						}
						else if(event._targetChoice&&event._targetChoice.has(card)){
							var targetChoice=event._targetChoice.get(card);
							if(!Array.isArray(targetChoice)||!targetChoice.contains(players[i])){
								nochess=false;
							}
						}
						else if(!event.filterTarget(card,player,players[i])){
							nochess=false;
						}
						if(nochess){
							if(ui.selected.targets.length<range[1]){
								players[i].classList.add('selectable');
								if(Array.isArray(event._targetChoice)){
									event._targetChoice.push(players[i]);
								}
							}
							else if(range[1]<=-1){
								players[i].classList.add('selected');
								ui.selected.targets.add(players[i]);
							}
							else{
								players[i].classList.remove('selectable');
							}
						}
						else{
							players[i].classList.remove('selectable');
							if(range[1]<=-1){
								players[i].classList.remove('selected');
								ui.selected.targets.remove(players[i]);
							}
						}
						if(players[i].classList.contains('selected')){
							players[i].classList.add('selectable');
						}
						else if(!selectableTargets&&players[i].classList.contains('selectable')){
							selectableTargets=true;
						}
						if(players[i].instance){
							if(players[i].classList.contains('selected')){
								players[i].instance.classList.add('selected');
							}
							else{
								players[i].instance.classList.remove('selected');
							}
							if(players[i].classList.contains('selectable')){
								players[i].instance.classList.add('selectable');
							}
							else{
								players[i].instance.classList.remove('selectable');
							}
						}
					}
					if(ui.selected.targets.length<range[0]){
						if(!event.forced||selectableTargets||event.complexSelect){
							ok=false;
						}
					}
					if(range[1]<=-1&&ui.selected.targets.length==0&&event.targetRequired){
						ok=false;
					}
				}
				if(custom.add.target){
					custom.add.target();
				}
			}
			if(!event.skill&&get.noSelected()&&!_status.noconfirm){
				var skills=[],enable,info;
				var skills2;
				if(event._skillChoice){
					skills2=event._skillChoice;
					for(var i=0;i<skills2.length;i++){
						if(event.isMine()||!event._aiexclude.contains(skills2[i])){
							skills.push(skills2[i]);
						}
					}
				}
				else{
					var skills2;
					if(get.mode()=='guozhan'&&player.hasSkillTag('nomingzhi',false,null,true)){
						skills2=player.getSkills(false,true,false);
					}
					else{
						skills2=player.getSkills('invisible',true,false);
					}
					skills2=game.filterSkills(skills2.concat(lib.skill.global),player,player.getSkills('e').concat(lib.skill.global));
					event._skillChoice=[];
					game.expandSkills(skills2);
					for(i=0;i<skills2.length;i++){
						info=get.info(skills2[i]);
						enable=false;
						if(typeof info.enable=='function') enable=info.enable(event);
						else if(Array.isArray(info.enable)) enable=info.enable.contains(event.name);
						else if(info.enable=='phaseUse') enable=(event.type=='phase');
						else if(typeof info.enable=='string') enable=(info.enable==event.name);
						if(enable){
							if(!game.expandSkills(player.getSkills(false).concat(lib.skill.global)).contains(skills2[i])&&(info.noHidden||get.mode()!='guozhan'||player.hasSkillTag('nomingzhi',false,null,true))) enable=false;
							if(info.filter&&!info.filter(event,player)) enable=false;
							if(info.viewAs&&typeof info.viewAs!='function'&&event.filterCard&&!event.filterCard(info.viewAs,player,event)) enable=false;
							if(info.viewAs&&typeof info.viewAs!='function'&&info.viewAsFilter&&info.viewAsFilter(player)==false) enable=false;
							if(info.usable&&get.skillCount(skills2[i])>=info.usable) enable=false;
							if(info.chooseButton&&_status.event.noButton) enable=false;
							if(info.round&&(info.round-(game.roundNumber-player.storage[skills2[i]+'_roundcount'])>0)) enable=false;
						}
						if(enable){
							if(event.isMine()||!event._aiexclude.contains(skills2[i])){
								skills.add(skills2[i]);
							}
							event._skillChoice.add(skills2[i]);
						}
					}
				}

				var globalskills=[];
				var globallist=lib.skill.global.slice(0);
				game.expandSkills(globallist);
				for(var i=0;i<skills.length;i++){
					if(globallist.contains(skills[i])){
						globalskills.push(skills.splice(i--,1)[0]);
					}
				}
				var equipskills=[];
				var ownedskills=player.getSkills('invisible',false);
				game.expandSkills(ownedskills);
				for(var i=0;i<skills.length;i++){
					if(!ownedskills.contains(skills[i])){
						equipskills.push(skills.splice(i--,1)[0]);
					}
				}
				if(equipskills.length){
					ui.create.skills3(equipskills);
				}
				else if(ui.skills3){
					ui.skills3.close();
				}
				if(skills.length){
					ui.create.skills(skills);
				}
				else if(ui.skills){
					ui.skills.close();
				}
				if(globalskills.length){
					ui.create.skills2(globalskills);
				}
				else if(ui.skills2){
					ui.skills2.close();
				}
			}
			else{
				if(ui.skills){
					ui.skills.close()
				}
				if(ui.skills2){
					ui.skills2.close()
				}
				if(ui.skills3){
					ui.skills3.close()
				}
			}
			_status.multitarget=false;
			var skillinfo=get.info(_status.event.skill);
			if(_status.event.name=='chooseToUse'){
				if(skillinfo&&skillinfo.multitarget&&!skillinfo.multiline){
					_status.multitarget=true;
				}
				if((skillinfo&&skillinfo.viewAs&&typeof skillinfo.viewAs!='function')||!_status.event.skill){
					var cardinfo=get.info(get.card());
					if(cardinfo&&(cardinfo.multitarget||cardinfo.complexSelect)&&!cardinfo.multiline){
						_status.multitarget=true;
					}
				}
			}
			else if(_status.event.multitarget){
				_status.multitarget=true;
			}
			if(event.isMine()){
				if(game.chess&&game.me&&get.config('show_distance')){
					for(var i=0;i<players.length;i++){
						if(players[i]==game.me){
							players[i].node.action.hide();
						}
						else{
							players[i].node.action.show();
							var dist=get.distance(game.me,players[i],'pure');
							var dist2=get.distance(game.me,players[i]);
							players[i].node.action.innerHTML='距离:'+dist2+'/'+dist;
							if(dist>7){
								players[i].node.action.classList.add('thunder');
							}
							else{
								players[i].node.action.classList.remove('thunder');
							}
						}
					}
				}
				if(ok&&(!event.filterOk||event.filterOk())&&auto&&(auto_confirm||(skillinfo&&skillinfo.direct))&&(!_status.mousedragging||!_status.mouseleft)&&
				!_status.mousedown&&!_status.touchnocheck){
					if(ui.confirm){
						if(!skillinfo||!skillinfo.preservecancel){
							ui.confirm.close();
						}
					}
					if(skillinfo&&skillinfo.preservecancel&&!ui.confirm){
						ui.create.confirm('c');
					}
					if(event.skillDialog==true) event.skillDialog=false;
					ui.click.ok();
					_status.mousedragging=null;
				}
				else{
					ui.arena.classList.add('selecting');
					if(event.filterTarget&&(!event.filterCard||!event.position||(typeof event.position=='string'&&event.position.indexOf('e')==-1))){
						ui.arena.classList.add('tempnoe');
					}
					game.countChoose();
					if(!_status.noconfirm&&!_status.event.noconfirm){
						if(!_status.mousedown||_status.mouseleft){
							var str='';
							if(ok&&(!event.filterOk||event.filterOk())) str+='o';
							if(!event.forced&&!event.fakeforce&&get.noSelected()) str+='c';
							ui.create.confirm(str);
						}
					}
				}
				if(ui.confirm&&ui.confirm.lastChild.link=='cancel'){
					if(_status.event.type=='phase'&&!_status.event.skill){
						ui.confirm.lastChild.innerHTML='结束';
					}
					else{
						ui.confirm.lastChild.innerHTML='取消';
					}
				}
			}
			return ok;
		},
		uncheck:function(){
			var i,j;
			if(game.chess){
				var shadows=ui.chessContainer.getElementsByClassName('playergrid temp');
				while(shadows.length){
					shadows[0].remove();
				}
			}
			var argc=arguments.length;
			var args=new Array(argc);
			for(var i=0;i<argc;i++){
				args[i]=arguments[i];
			}
			if((args.length==0||args.contains('card'))&&_status.event.player){
				var cards=_status.event.player.getCards('hejsx');
				for(j=0;j<cards.length;j++){
					cards[j].classList.remove('selected');
					cards[j].classList.remove('selectable');
					if(cards[j]._tempName){
						cards[j]._tempName.delete();
						delete cards[j]._tempName;
					}
					cards[j].updateTransform();
				}
				ui.selected.cards.length=0;
				_status.event.player.node.equips.classList.remove('popequip');
			}
			var players=game.players.slice(0);
			if(_status.event.deadTarget) players.addArray(game.dead);
			if((args.length==0||args.contains('target'))){
				for(j=0;j<players.length;j++){
					players[j].classList.remove('selected');
					players[j].classList.remove('selectable');
					if(players[j].instance){
						players[j].instance.classList.remove('selected');
						players[j].instance.classList.remove('selectable');
					}
				}
				ui.selected.targets.length=0;
			}
			if((args.length==0||args.contains('button'))&&_status.event.dialog&&_status.event.dialog.buttons){
				for(var j=0;j<_status.event.dialog.buttons.length;j++){
					_status.event.dialog.buttons[j].classList.remove('selectable');
					_status.event.dialog.buttons[j].classList.remove('selected');
				}
				ui.selected.buttons.length=0;
			}
			if(args.length==0){
				ui.arena.classList.remove('selecting');
				ui.arena.classList.remove('tempnoe');
				_status.imchoosing=false;
				_status.lastdragchange.length=0;
				_status.mousedragging=null;
				_status.mousedragorigin=null;

				while(ui.touchlines.length){
					ui.touchlines.shift().delete();
				}
			}
			ui.canvas.width=ui.arena.offsetWidth;
			ui.canvas.height=ui.arena.offsetHeight;
			for(var i=0;i<players.length;i++){
				players[i].unprompt();
			}
			for(var i=0;i<_status.dragline.length;i++){
				if(_status.dragline[i]) _status.dragline[i].remove();
			}
			ui.arena.classList.remove('dragging');
			_status.dragline.length=0;
		},
		swapSeat:function(player1,player2,prompt,behind,noanimate){
			if(noanimate){
				player1.style.transition='all 0s';
				player2.style.transition='all 0s';
				ui.refresh(player1);
				ui.refresh(player2);
			}
			if(behind){
				var totalPopulation=game.players.length+game.dead.length+1;
				for(var iwhile=0;iwhile<totalPopulation;iwhile++){
					if(player1.next!=player2){
						game.swapSeat(player1,player1.next,false,false);
					}
					else{
						break;
					}
				}
				if(prompt!=false){
					game.log(player1,'将座位移至',player2,'后');
				}
			}
			else{
				game.addVideo('swapSeat',null,[player1.dataset.position,player2.dataset.position]);
				var seat1=player1.seatNum;
				var seat2=player2.seatNum;
				player2.seatNum=seat1;
				player1.seatNum=seat2;
				var temp1,pos,i,num;
				temp1=player1.dataset.position;
				player1.dataset.position=player2.dataset.position;
				player2.dataset.position=temp1;
				game.arrangePlayers();
				if(!game.chess){
					if(player1.dataset.position=='0'||player2.dataset.position=='0'){
						pos=parseInt(player1.dataset.position);
						if(pos==0) pos=parseInt(player2.dataset.position);
						num=game.players.length+game.dead.length;
						for(i=0;i<game.players.length;i++){
							temp1=parseInt(game.players[i].dataset.position)-pos;
							if(temp1<0) temp1+=num;
							game.players[i].dataset.position=temp1;
						}
						for(i=0;i<game.dead.length;i++){
							temp1=parseInt(game.dead[i].dataset.position)-pos;
							if(temp1<0) temp1+=num;
							game.dead[i].dataset.position=temp1;
						}
					}
				}
				if(prompt!=false){
					game.log(player1,'和',player2,'交换了座位');
				}
			}
			if(noanimate){
				setTimeout(function(){
					player1.style.transition='';
					player2.style.transition='';
				},200);
			}
		},
		swapPlayer:function(player,player2){
			if(player2){
				if(player==game.me) game.swapPlayer(player2);
				else if(player2==game.me) game.swapPlayer(player);
			}
			else{
				if(player==game.me) return;
				var players=game.players.concat(game.dead);
				for(var i=0;i<players.length;i++){
					players[i].style.transition='all 0s';
				}
				game.addVideo('swapPlayer',player,get.cardsInfo(player.getCards('h')));
				if(!game.chess){
					var pos=parseInt(player.dataset.position);
					var num=game.players.length+game.dead.length;
					var players=game.players.concat(game.dead);
					var temp;
					for(var i=0;i<players.length;i++){
						temp=parseInt(players[i].dataset.position)-pos;
						if(temp<0) temp+=num;
						players[i].dataset.position=temp;
					}
				}
				game.me.node.handcards1.remove();
				game.me.node.handcards2.remove();
				var current=game.me;
				game.me=player;
				if(current.isDead()){
					current.$die();
				}
				ui.handcards1=player.node.handcards1.animate('start').fix();
				ui.handcards2=player.node.handcards2.animate('start').fix();
				ui.handcards1Container.appendChild(ui.handcards1);
				ui.handcards2Container.appendChild(ui.handcards2);

				ui.updatehl();
			}
			if(game.me.isAlive()){
				if(ui.auto) ui.auto.show();
				if(ui.wuxie) ui.wuxie.show();
				if(ui.revive){
					ui.revive.close();
					delete ui.revive;
				}
				if(ui.swap){
					ui.swap.close();
					delete ui.swap;
				}
				if(ui.restart){
					ui.restart.close();
					delete ui.restart;
				}
				if(ui.continue_game){
					ui.continue_game.close();
					delete ui.continue_game;
				}
			}
			if(lib.config.mode=='identity'){
				game.me.setIdentity(game.me.identity);
			}
			setTimeout(function(){
				for(var i=0;i<players.length;i++){
					players[i].style.transition='';
				}
			},100);
		},
		swapControl:function(player){
			if(player==game.me) return;

			game.me.node.handcards1.remove();
			game.me.node.handcards2.remove();

			game.me=player;
			ui.handcards1=player.node.handcards1.animate('start').fix();
			ui.handcards2=player.node.handcards2.animate('start').fix();
			ui.handcards1Container.insertBefore(ui.handcards1,ui.handcards1Container.firstChild);
			ui.handcards2Container.insertBefore(ui.handcards2,ui.handcards2Container.firstChild);
			ui.updatehl();
			game.addVideo('swapControl',player,get.cardsInfo(player.getCards('h')));

			if(game.me.isAlive()){
				if(ui.auto) ui.auto.show();
				if(ui.wuxie) ui.wuxie.show();
				if(ui.revive){
					ui.revive.close();
					delete ui.revive;
				}
				if(ui.swap){
					ui.swap.close();
					delete ui.swap;
				}
				if(ui.restart){
					ui.restart.close();
					delete ui.restart;
				}
				if(ui.continue_game){
					ui.continue_game.close();
					delete ui.continue_game;
				}
			}
		},
		swapPlayerAuto:function(player){
			if(game.modeSwapPlayer){
				game.modeSwapPlayer(player);
			}
			else{
				game.swapPlayer(player);
			}
		},
		findNext:function(player){
			var players=get.players(lib.sort.position);
			var position=parseInt(player.dataset.position);
			for(var i=0;i<players.length;i++){
				if(parseInt(players[i].dataset.position)>=position){
					return players[i];
				}
			}
			return players[0];
		},
		loadModeAsync:function(name,callback){
			window.game=game;
			var script=lib.init.js(lib.assetURL+'mode',name,gnc.of(function*(){
				yield Promise.allSettled(_status.importing.mode);
				if(!lib.config.dev) delete window.game;
				script.remove();
				var content=lib.imported.mode[name];
				delete lib.imported.mode[name];
				if(get.is.empty(lib.imported.mode)){
					delete lib.imported.mode;
				}
				callback(content);
			}));
		},
		switchMode:function(name,configx){
			if(!lib.layoutfixed.contains(name)){
				if(lib.config.layout!=game.layout){
					lib.init.layout(lib.config.layout);
				}
				else if(lib.config.mode=='brawl'){
					if(lib.config.player_border=='normal'&&(game.layout=='long'||game.layout=='long2')){
						ui.arena.classList.add('lslim_player');
					}
				}
			}
			window.game=game;
			var script=lib.init.js(lib.assetURL+'mode',name,gnc.of(function*(){
				yield Promise.allSettled(_status.importing.mode);
				if(!lib.config.dev) delete window.game;
				script.remove();
				var mode=lib.imported.mode;
				_status.sourcemode=lib.config.mode;
				lib.config.mode=name;

				var i,j,k;
				for(i in mode[lib.config.mode].element){
					if(!lib.element[i]) lib.element[i]=[];
					for(j in mode[lib.config.mode].element[i]){
						if(j=='init'){
							if(!lib.element[i].inits) lib.element[i].inits=[];
							lib.element[i].inits.push(mode[lib.config.mode].element[i][j]);
						}
						else{
							lib.element[i][j]=mode[lib.config.mode].element[i][j];
						}
					}
				}
				for(i in mode[lib.config.mode].ai){
					if(typeof mode[lib.config.mode].ai[i]=='object'){
						if(ai[i]==undefined) ai[i]={};
						for(j in mode[lib.config.mode].ai[i]){
							ai[i][j]=mode[lib.config.mode].ai[i][j];
						}
					}
					else{
						ai[i]=mode[lib.config.mode].ai[i];
					}
				}
				for(i in mode[lib.config.mode].ui){
					if(typeof mode[lib.config.mode].ui[i]=='object'){
						if(ui[i]==undefined) ui[i]={};
						for(j in mode[lib.config.mode].ui[i]){
							ui[i][j]=mode[lib.config.mode].ui[i][j];
						}
					}
					else{
						ui[i]=mode[lib.config.mode].ui[i];
					}
				}
				for(i in mode[lib.config.mode].game){
					game[i]=mode[lib.config.mode].game[i];
				}
				for(i in mode[lib.config.mode].get){
					get[i]=mode[lib.config.mode].get[i];
				}
				if(game.onwash){
					lib.onwash.push(game.onwash);
					delete game.onwash;
				}
				if(game.onover){
					lib.onover.push(game.onover);
					delete game.onover;
				}
				lib.config.banned=lib.config[lib.config.mode+'_banned']||[];
				lib.config.bannedcards=lib.config[lib.config.mode+'_bannedcards']||[];

				for(i in mode[lib.config.mode]){
					if(i=='element') continue;
					if(i=='game') continue;
					if(i=='ai') continue;
					if(i=='ui') continue;
					if(i=='get') continue;
					if(i=='config') continue;
					if(i=='start') continue;
					if(i=='startBefore') continue;
					if(lib[i]==undefined) lib[i]=(Array.isArray(mode[lib.config.mode][i]))?[]:{};
					for(j in mode[lib.config.mode][i]){
						lib[i][j]=mode[lib.config.mode][i][j];
					}
				}

				// var pilecfg=lib.config.customcardpile[get.config('cardpilename')];
				// if(pilecfg){
				//     lib.config.bannedpile=pilecfg[0]||{};
				//     lib.config.addedpile=pilecfg[1]||{};
				// }

				_status.event={
					finished:true,
					next:[],
					after:[]
				};
				_status.paused=false;

				if(_status.connectMode&&lib.mode[name].connect){
					game.saveConfig('connect_mode',name);
					game.clearConnect();
					lib.configOL.mode=name;
					if(configx){
						for(var i in configx){
							lib.configOL[i]=configx[i];
						}
					}
					else{
						for(var i in lib.mode[name].connect){
							if(i=='update') continue;
							lib.configOL[i.slice(8)]=get.config(i);
						}
						lib.configOL.zhinang_tricks=lib.config.connect_zhinang_tricks;
						lib.configOL.characterPack=lib.connectCharacterPack.slice(0);
						lib.configOL.cardPack=lib.connectCardPack.slice(0);
						for(var i=0;i<lib.config.connect_characters.length;i++){
							lib.configOL.characterPack.remove(lib.config.connect_characters[i]);
						}
						for(var i=0;i<lib.config.connect_cards.length;i++){
							lib.configOL.cardPack.remove(lib.config.connect_cards[i]);
						}
						lib.configOL.banned=lib.config['connect_'+name+'_banned'];
						lib.configOL.bannedcards=lib.config['connect_'+name+'_bannedcards'];
					}
					lib.configOL.version=lib.versionOL;
					for(var i in lib.cardPackList){
						if(lib.configOL.cardPack.contains(i)){
							lib.card.list=lib.card.list.concat(lib.cardPackList[i]);
						}
					}
					for(i=0;i<lib.card.list.length;i++){
						if(lib.card.list[i][2]=='huosha'){
							lib.card.list[i]=lib.card.list[i].slice(0);
							lib.card.list[i][2]='sha';
							lib.card.list[i][3]='fire';
						}
						else if(lib.card.list[i][2]=='leisha'){
							lib.card.list[i]=lib.card.list[i].slice(0);
							lib.card.list[i][2]='sha';
							lib.card.list[i][3]='thunder';
						}
						if(!lib.card[lib.card.list[i][2]]){
							lib.card.list.splice(i,1);i--;
						}
						else if(lib.card[lib.card.list[i][2]].mode&&
							lib.card[lib.card.list[i][2]].mode.contains(lib.config.mode)==false){
							lib.card.list.splice(i,1);i--;
						}
					}
				}

				if(!lib.config.show_playerids||!game.showIdentity){
					ui.playerids.style.display='none';
				}
				else{
					ui.playerids.style.display='';
				}

				if(mode[lib.config.mode].startBefore) mode[lib.config.mode].startBefore();
				game.createEvent('game',false).setContent(mode[lib.config.mode].start);
				if(lib.mode[lib.config.mode]&&lib.mode[lib.config.mode].fromextension){
					var startstr=mode[lib.config.mode].start.toString();
					if(startstr.indexOf('onfree')==-1){
						setTimeout(lib.init.onfree,500);
					}
				}
				delete lib.imported.mode[name];

				if(!lib.db){
					try{
						lib.storage=JSON.parse(localStorage.getItem(lib.configprefix+lib.config.mode));
						if(typeof lib.storage!='object') throw('err');
						if(lib.storage==null) throw('err');
					}
					catch(err){
						lib.storage={};
						localStorage.setItem(lib.configprefix+lib.config.mode,"{}");
					}
					game.loop();
				}
				else{
					game.getDB('data',lib.config.mode,function(obj){
						lib.storage=obj||{};
						game.loop();
					});
				}
			}));
		},
		loadMode:function(mode){
			var next=game.createEvent('loadMode',false);
			next.mode=mode;
			next.setContent('loadMode');
		},
		loadPackage:function(){
			var next=game.createEvent('loadPackage');
			next.packages=[];
			for(var i=0;i<arguments.length;i++){
				if(typeof arguments[i]=='string'){
					next.packages.push(arguments[i]);
				}
			}
			next.setContent('loadPackage');
		},
		phaseLoop:function(player){
			var next=game.createEvent('phaseLoop');
			next.player=player;
			next._isStandardLoop=true;
			next.setContent('phaseLoop');
		},
		gameDraw:function(player,num){
			var next=game.createEvent('gameDraw');
			next.player=player||game.me;
			if(num==undefined) next.num=4;
			else next.num=num;
			next.setContent('gameDraw');
			return next;
		},
		chooseCharacterDouble:function(){
			var next=game.createEvent('chooseCharacter');
			var config,width,num,ratio,func,update,list,first;
			for(var i=0;i<arguments.length;i++){
				if(typeof arguments[i]=='number'){
					if(!width){
						width=arguments[i];
					}
					else if(!num){
						num=arguments[i];
					}
					else{
						ratio=arguments[i];
					}
				}
				else if(typeof arguments[i]=='function'){
					if(!func){
						func=arguments[i];
					}
					else{
						update=arguments[i];
					}
				}
				else if(Array.isArray(arguments[i])){
					list=arguments[i];
				}
				else if(get.objtype(arguments[i])=='object'){
					config=arguments[i];
				}
			}
			if(!config){
				list=config;
				config={};
			}
			config.width=config.width||width||8;
			config.height=4;
			config.size=config.width*config.height;
			config.num=config.num||num||3;
			config.ratio=config.ratio||ratio||1.2;
			config.update=config.update||update;
			if(!config.hasOwnProperty('first')){
				if(typeof first=='boolean'){
					config.first=first;
				}
				else{
					config.first='rand';
				}
			}
			if(!list){
				list=[];
				for(var i in lib.character){
					if(typeof func=='function'){
						if(!func(i)) continue;
					}
					else{
						if(lib.filter.characterDisabled(i)) continue;
					}
					list.push(i);
				}
			}
			next.config=config;
			next.list=list;
			next.setContent(function(){
				'step 0'
				event.nodes=[];
				event.avatars=[];
				event.friend=[];
				event.enemy=[];
				event.blank=[];
				for(var i=0;i<event.config.size;i++){
					event.nodes.push(ui.create.div('.shadowed.reduce_radius.choosedouble'));
				}
				event.moveAvatar=function(node,i){
					if(!node.classList.contains('moved')){
						event.blank.push(node.index);
					}
					event.nodes[node.index].style.display='';
					event.nodes[node.index].show();
					clearTimeout(event.nodes[node.index].choosetimeout);
					event.moveNode(node,i);
					var nodex=event.nodes[node.index];
					nodex.choosetimeout=setTimeout(function(){
						nodex.hide();
						nodex.choosetimeout=setTimeout(function(){
							nodex.show();
							nodex.style.display='none';
						},300);
					},400);
				};
				event.aiMove=function(friend){
					var list=[];
					for(var i=0;i<event.avatars.length;i++){
						if(!event.avatars[i].classList.contains('moved')){
							list.push(event.avatars[i]);
						}
					}
					for(var i=0;i<list.length;i++){
						if(Math.random()<0.7||i==list.length-1){
							if(friend){
								event.moveAvatar(list[i],event.friend.length+event.config.width*(event.config.height-1));
								event.friend.push(list[i]);
							}
							else{
								event.moveAvatar(list[i],event.enemy.length);
								event.enemy.push(list[i]);
							}
							list[i].classList.add('moved');
							break;
						}
					}
				};
				event.promptbar=ui.create.div('.hidden',ui.window);
				event.promptbar.style.width='100%';
				event.promptbar.style.left=0;
				if(get.is.phoneLayout()){
					event.promptbar.style.top='20px';
				}
				else{
					event.promptbar.style.top='58px';
				}
				event.promptbar.style.pointerEvents='none';
				event.promptbar.style.textAlign='center';
				event.promptbar.style.zIndex='2';
				ui.create.div('.shadowed.reduce_radius',event.promptbar);
				event.promptbar.firstChild.style.fontSize='18px';
				event.promptbar.firstChild.style.padding='6px 10px';
				event.promptbar.firstChild.style.position='relative';
				event.prompt=function(str){
					event.promptbar.firstChild.innerHTML=str;
					event.promptbar.show();
				};
				event.moveNode=function(node,i){
					var width=event.width,height=event.height,margin=event.margin;
					var left=-(width+10)*event.config.width/2+5+(i%event.config.width)*(width+10);
					var top=-(height+10)*event.config.height/2+5+Math.floor(i/event.config.width)*(height+10)+margin/2;
					node.style.transform='translate('+left+'px,'+top+'px)';
					node.index=i;
				};
				event.resize=function(){
					var margin=0;
					if(!get.is.phoneLayout()){
						margin=38;
					}
					var height=(ui.window.offsetHeight-10*(event.config.height+1)-margin)/event.config.height;
					var width=(ui.window.offsetWidth-10*(event.config.width+1))/event.config.width;
					if(width*event.config.ratio<height){
						height=width*event.config.ratio;
					}
					else{
						width=height/event.config.ratio;
					}
					event.width=width;
					event.height=height;
					event.margin=margin;
					for(var i=0;i<event.config.size;i++){
						event.moveNode(event.nodes[i],i);
						event.nodes[i].style.width=width+'px';
						event.nodes[i].style.height=height+'px';
						if(event.avatars[i]){
							event.moveNode(event.avatars[i],event.avatars[i].index);
							event.avatars[i].style.width=width+'px';
							event.avatars[i].style.height=height+'px';
							event.avatars[i].nodename.style.fontSize=Math.max(14,Math.round(width/5.6))+'px';
						}
					}
					if(event.deciding){
						var str='px,'+(event.margin/2-event.height*0.5)+'px)';
						for(var i=0;i<event.friendlist.length;i++){
							event.friendlist[i].style.transform='scale(1.2) translate('+(-(event.width+14)*event.friendlist.length/2+7+i*(event.width+14))+str;
						}
					}
				};
				lib.onresize.push(event.resize);
				event.clickAvatar=function(){
					if(event.deciding){
						if(this.index<event.config.width) return;
						if(event.friendlist.contains(this)){
							event.friendlist.remove(this);
							event.moveNode(this,this.index);
							this.nodename.innerHTML=get.slimName(this.link);
						}
						else{
							event.friendlist.push(this);
						}
						if(event.friendlist.length==event.config.num){
							event.deciding=false;
							event.prompt('比赛即将开始');
							setTimeout(game.resume,1000);
						}
						if(event.config.update){
							for(var i=0;i<event.friendlist.length;i++){
								event.friendlist[i].nodename.innerHTML=event.config.update(i,event.friendlist.length)||event.friendlist[i].nodename.innerHTML;
							}
						}
						var str='px,'+(event.margin/2-event.height*0.5)+'px)';
						for(var i=0;i<event.friendlist.length;i++){
							event.friendlist[i].style.transform='scale(1.2) translate('+(-(event.width+14)*event.friendlist.length/2+7+i*(event.width+14))+str;
						}
					}
					else{
						if(!event.imchoosing) return;
						if(event.replacing){
							this.link=event.replacing;
							this.setBackground(event.replacing,'character');

							this.nodename.innerHTML=get.slimName(event.replacing);
							this.nodename.dataset.nature=get.groupnature(lib.character[event.replacing][1]);

							delete event.replacing;
							if(this.classList.contains('moved')){
								event.custom.add.window();
							}
						}
						if(this.classList.contains('moved')) return;
						event.moveAvatar(this,event.friend.length+event.config.width*(event.config.height-1));
						event.friend.push(this.link);
						this.classList.add('moved');
						game.resume();
					}
				};
				event.skipnode=ui.create.system('跳过',function(){
					this.remove();
					event._skiprest=true;
					if(event.imchoosing){
						game.resume();
					}
				});
				if(get.config('change_choice')){
					event.replacenode=ui.create.system('换将',function(){
						event.promptbar.hide();
						while(event.avatars.length){
							event.avatars.shift().remove();
						}
						for(var i=0;i<event.config.size;i++){
							event.nodes[i].show();
							event.nodes[i].style.display='';
							clearTimeout(event.nodes[i].choosetimeout);
						}
						delete event.list2;
						event.friend.length=0;
						event.enemy.length=0;
						event.blank.length=0;
						event.redoing=true;
						if(event.imchoosing){
							game.resume();
						}
					},true);
				}
				if(get.config('change_choice')){
					event.reselectnode=ui.create.system('重选',function(){
						event.promptbar.hide();
						event.list2=event.list2.concat(event.friend).concat(event.enemy);
						event.friend.length=0;
						event.enemy.length=0;
						for(var i=0;i<event.avatars.length;i++){
							if(event.avatars[i].classList.contains('moved')){
								event.moveAvatar(event.avatars[i],event.blank.randomRemove());
								event.avatars[i].classList.remove('moved');
							}
						}
						event.redoing=true;
						if(event.imchoosing){
							game.resume();
						}
					},true);
				}
				if(get.config('free_choose')){
					var createCharacterDialog=function(){
						event.freechoosedialog=ui.create.characterDialog();
						event.freechoosedialog.style.height='80%';
						event.freechoosedialog.style.top='10%';
						event.freechoosedialog.style.transform='scale(0.8)';
						event.freechoosedialog.style.transition='all 0.3s';
						event.freechoosedialog.listen(function(e){
							if(!event.replacing){
								event.dialoglayer.clicked=true;
							}
						});
						event.freechoosedialog.classList.add('pointerdialog');
						event.dialoglayer=ui.create.div('.popup-container.hidden',function(e){
							if(this.classList.contains('removing')) return;
							if(this.clicked){
								this.clicked=false;
								return;
							}
							ui.window.classList.remove('modepaused');
							this.delete();
							e.stopPropagation();
							event.freechoosedialog.style.transform='scale(0.8)';
							if(event.replacing){
								event.prompt('用'+get.translation(event.replacing)+'替换一名武将');
							}
							else{
								if(event.side==0){
									event.prompt('请选择两名武将');
								}
								else{
									event.prompt('请选择一名武将');
								}
							}
						});
						event.dialoglayer.classList.add('modenopause');
						event.dialoglayer.appendChild(event.freechoosedialog);
						event.freechoosenode.classList.remove('hidden');
					}

					event.custom.replace.button=function(button){
						event.replacing=button.link;
					};
					event.custom.add.window=function(){
						if(event.replacing){
							delete event.replacing;
							if(event.side==0){
								event.prompt('请选择两名武将');
							}
							else{
								event.prompt('请选择一名武将');
							}
						}
					};
					event.freechoosenode=ui.create.system('自由选将',function(){
						if(this.classList.contains('hidden')) return;
						if(!event.imchoosing){
							event.prompt('请等待敌方选将');
							return;
						}
						delete event.replacing;
						ui.window.classList.add('modepaused');
						ui.window.appendChild(event.dialoglayer);
						ui.refresh(event.dialoglayer);
						event.dialoglayer.show();
						event.freechoosedialog.style.transform='scale(1)';
						event.promptbar.hide();
					},true);
					if(lib.onfree){
						event.freechoosenode.classList.add('hidden');
						lib.onfree.push(createCharacterDialog);
					}
					else{
						createCharacterDialog();
					}
				}
				event.checkredo=function(){
					if(event.redoing){
						event.goto(1);
						delete event.redoing;
						return true;
					}
				};
				// if(ui.cardPileButton) ui.cardPileButton.style.display='none';
				ui.auto.hide();
				ui.wuxie.hide();
				event.resize();
				for(var i=0;i<event.config.size;i++){
					ui.window.appendChild(event.nodes[i]);
				}
				'step 1'
				var rand=event.config.first;
				if(rand=='rand'){
					rand=(Math.random()<0.5);
				}
				if(rand){
					_status.color=true;
					event.side=1;
				}
				else{
					_status.color=false;
					event.side=3;
				}
				if(!event.list2){
					event.list2=event.list.randomGets(event.config.width*2);
					for(var i=0;i<event.config.width*2;i++){
						event.avatars.push(ui.create.div('.shadowed.shadowed2.reduce_radius.character.choosedouble',event.clickAvatar));
						var name=event.list2[i];
						event.avatars[i].setBackground(name,'character');
						event.avatars[i].link=name;
						event.avatars[i].nodename=ui.create.div('.name',event.avatars[i],get.slimName(name));
						event.avatars[i].nodename.style.fontFamily=lib.config.name_font;
						event.avatars[i].index=i+event.config.width;
						event.avatars[i].animate('start');
						event.nodes[event.avatars[i].index].style.display='none';
						event.avatars[i].nodename.dataset.nature=get.groupnature(lib.character[name][1]);
						lib.setIntro(event.avatars[i]);
					}
					event.resize();
					for(var i=0;i<event.avatars.length;i++){
						ui.window.appendChild(event.avatars[i]);
					}
					event.avatars.sort(function(a,b){
						return get.rank(b.link,true)-get.rank(a.link,true);
					})
				}
				game.delay();
				lib.init.onfree();
				'step 2'
				if(event.checkredo()) return;
				if(event._skiprest) return;
				if(event.side<2){
					event.imchoosing=true;
					if(event.side==0){
						event.prompt('请选择两名武将');
					}
					else{
						event.prompt('请选择一名武将');
						event.fast=get.time();
					}
					game.pause();
				}
				else{
					event.aiMove();
					game.delay();
				}
				'step 3'
				if(typeof event.fast=='number'&&get.time()-event.fast<=1000){
					event.fast=true;
				}
				else{
					event.fast=false;
				}
				delete event.imchoosing;
				if(event.checkredo()) return;
				if(event._skiprest){
					while(event.enemy.length<event.config.width){
						event.aiMove();
					}
					while(event.friend.length<event.config.width){
						event.aiMove(true);
					}
				}
				else if(event.friend.length+event.enemy.length<event.config.width*2-1){
					if(event.side==1){
						game.delay(event.fast?1:2);
						event.promptbar.hide();
					}
					event.side++;
					if(event.side>3){
						event.side=0;
					}
					event.goto(2);
				}
				else{
					event.promptbar.hide();
					event.side++;
					if(event.side>3){
						event.side=0;
					}
					if(event.side>=2){
						game.delay()
					}
				}
				'step 4'
				if(event.checkredo()) return;
				if(event.skipnode) event.skipnode.delete();
				if(event.replacenode) event.replacenode.delete();
				if(event.reselectnode) event.reselectnode.delete();
				if(event.freechoosenode) event.freechoosenode.delete();
				for(var i=0;i<event.avatars.length;i++){
					if(!event.avatars[i].classList.contains('moved')){
						if(event.side<2){
							event.moveAvatar(event.avatars[i],event.friend.length+event.config.width*(event.config.height-1));
							event.friend.push(event.avatars[i]);
						}
						else{
							event.moveAvatar(event.avatars[i],event.enemy.length);
							event.enemy.push(event.avatars[i]);
						}
						event.avatars[i].classList.add('moved');
					}
				}
				game.delay();
				'step 5'
				event.prompt('选择'+get.cnNumber(event.config.num)+'名出场武将');
				event.enemylist=[];
				for(var i=0;i<event.avatars.length;i++){
					if(event.avatars[i].index>event.config.width){
						event.avatars[i].classList.add('selecting');
					}
				}
				var rand=[];
				for(var i=0;i<event.config.width;i++){
					for(var j=0;j<event.config.width-i;j++){
						rand.push(i);
					}
				}
				for(var i=0;i<event.config.num;i++){
					var rand2=rand.randomGet();
					for(var j=0;j<rand.length;j++){
						if(rand[j]==rand2){
							rand.splice(j--,1);
						}
					}
					event.enemylist.push(event.enemy[rand2]);
				}
				event.enemylist.randomSort();
				event.friendlist=[];
				event.deciding=true;
				for(var i=0;i<event.config.size;i++){
					event.nodes[i].hide();
				}
				game.pause();
				'step 6'
				event.promptbar.delete();
				if(ui.cardPileButton) ui.cardPileButton.style.display='';
				lib.onresize.remove(event.resize);
				ui.wuxie.show();
				ui.auto.show();
				for(var i=0;i<event.avatars.length;i++){
					event.avatars[i].delete();
				}
				for(var i=0;i<event.nodes.length;i++){
					event.nodes[i].delete();
				}
				event.result={friend:[],enemy:[]};
				for(var i=0;i<event.config.num;i++){
					event.result.friend[i]=event.friendlist[i].link;
					event.result.enemy[i]=event.enemylist[i].link;
				}
			});
		},
		updateRoundNumber:()=>game.broadcastAll((num1,num2,top)=>{
			if(ui.cardPileNumber) ui.cardPileNumber.innerHTML=`${num1}轮 剩余牌: ${num2}`;
			_status.pileTop=top;
		},game.roundNumber,ui.cardPile.childNodes.length,ui.cardPile.firstChild),
		asyncDraw:(players,num,drawDeck,bottom)=>players.forEach((value,index)=>{
			let num2=1;
			if(typeof num=='number') num2=num;
			else if(Array.isArray(num)) num2=num[index];
			else if(typeof num=='function') num2=num(value);
			if(drawDeck&&drawDeck.drawDeck) value.draw(num2,false,drawDeck);
			else if(bottom) value.draw(num2,'nodelay','bottom');
			else value.draw(num2,'nodelay');
		}),
		asyncDrawAuto:function(players,num,drawDeck){
			if(players.length>1){
				game.asyncDraw.apply(this,arguments);
				return;
			}
			let num2=1;
			if(typeof num=='number') num2=num;
			else if(Array.isArray(num)) num2=num[0];
			else if(typeof num=='function') num2=num(players[0]);
			if(drawDeck&&drawDeck.drawDeck) players[0].draw(num2,drawDeck);
			else players[0].draw(num2);
		},
		finishSkill:(i,sub)=>{
			const mode=get.mode(),info=lib.skill[i],iInfo=`${i}_info`;
			if(info.alter){
				lib.translate[`${iInfo}_origin`]=lib.translate[iInfo];
				if(!lib.config.vintageSkills.contains(i)) lib.translate[iInfo]=lib.translate[`${iInfo}_alter`];
			}
			else if(lib.translate[`${iInfo}_${mode}`]) lib.translate[iInfo]=lib.translate[`${iInfo}_${mode}`];
			else if(lib.translate[`${iInfo}_zhu`]&&(mode=='identity'||mode=='guozhan'&&_status.mode=='four')) lib.translate[iInfo]=lib.translate[`${iInfo}_zhu`];
			else if(lib.translate[`${iInfo}_combat`]&&get.is.versus()) lib.translate[iInfo]=lib.translate[`${iInfo}_combat`];
			if(info.forbid&&info.forbid.contains(mode)){
				lib.skill[i]={};
				if(lib.translate[iInfo]) lib.translate[iInfo]='此模式下不可用';
				return;
			}
			if(info.mode&&info.mode.contains(mode)==false){
				lib.skill[i]={};
				if(lib.translate[iInfo]) lib.translate[iInfo]='此模式下不可用';
				return;
			}
			if(info.available&&info.available(mode)==false){
				lib.skill[i]={};
				if(lib.translate[iInfo]) lib.translate[iInfo]='此模式下不可用';
				return;
			}
			if(info.viewAs&&typeof info.viewAs!='function'){
				if(typeof info.viewAs=='string') info.viewAs={
					name:info.viewAs
				};
				if(!lib.card[info.viewAs.name]){
					lib.skill[i]={};
					lib.translate[iInfo]='技能不可用';
					return;
				}
				if(info.ai==undefined) info.ai={};
				const skill=info.ai,card=lib.card[info.viewAs.name].ai;
				if(card) Object.keys(card).forEach(value=>{
					if(skill[value]==undefined) skill[value]=card[value];
					else if(typeof skill[value]=='object') Object.keys(card[value]).forEach(element=>{
						if(skill[value][element]==undefined) skill[value][element]=card[value][element];
					});
				});
			}
			if(info.inherit){
				const skill=lib.skill[info.inherit];
				if(skill) Object.keys(skill).forEach(value=>{
					if(info[value]!=undefined) return;
					if(value=='audio'&&(typeof info[value]=='number'||typeof info[value]=='boolean')) info[value]=info.inherit;
					else info[value]=skill[value];
				});
				if(lib.translate[i]==undefined) lib.translate[i]=lib.translate[info.inherit];
				if(lib.translate[iInfo]==undefined) lib.translate[iInfo]=lib.translate[`${info.inherit}_info`];
			}
			if(info.limited){
				if(info.mark===undefined) info.mark=true;
				if(!info.intro) info.intro={};
				if(info.intro.content===undefined) info.intro.content='limited';
				if(info.skillAnimation===undefined) info.skillAnimation=true;
				if(info.init===undefined) info.init=(player,skill)=>player.storage[skill]=false;
			}
			if(info.subSkill&&!sub) Object.keys(info.subSkill).forEach(value=>{
				const iValue=`${i}_${value}`;
				lib.skill[iValue]=info.subSkill[value];
				lib.skill[iValue].sub=true;
				if(info.subSkill[value].name) lib.translate[iValue]=info.subSkill[value].name;
				else lib.translate[iValue]=lib.translate[iValue]||lib.translate[i];
				if(info.subSkill[value].description) lib.translate[`${iValue}_info`]=info.subSkill[value].description;
				if(info.subSkill[value].marktext) lib.translate[`${iValue}_bg`]=info.subSkill[value].marktext;
				game.finishSkill(iValue,true);
			});
			if(info.round){
				const k=`${i}_roundcount`;
				if(typeof info.group=='string') info.group=[info.group,k];
				else if(Array.isArray(info.group)) info.group.add(k);
				else info.group=[k];
				lib.skill[k]=((round,name)=>({
					init:player=>{
						if(typeof player.storage[name]!=='number') player.storage[name]=1-round;
					},
					intro:{
						content:(storage,player)=>{
							let str='';
							const info=get.info(name.slice(0,name.indexOf('_roundcount')));
							if(info&&info.addintro) str+=info.addintro(storage,player);
							const num=round-(game.roundNumber-storage);
							if(num>0) str+=`${get.cnNumber(num)}轮后${info.roundtext||'技能重置'}`;
							else str+='技能可发动';
							return str;
						},
						markcount:(storage,player)=>Math.max(round-(game.roundNumber-storage),0)
					},
					trigger:{global:'roundStart'},
					forced:true,
					popup:false,
					silent:true,
					content:()=>{
						if(lib.skill[event.name.slice(0,event.name.indexOf('_roundcount'))].round-(game.roundNumber-player.storage[event.name])>0) player.updateMarks();
						else player.unmarkSkill(event.name);
					}
				}))(info.round,k);
				lib.translate[k]=lib.translate[i]||'';
				lib.translate[`${k}_bg`]=lib.translate[`${i}_bg`]||lib.translate[k][0];
			}
			if(info.marktext) lib.translate[`${i}_bg`]=info.marktext;
			if(info.silent){
				if(!info.hasOwnProperty('forced')) info.forced=true;
				if(!info.hasOwnProperty('popup')) info.popup=false;
			}
			if(!info.hasOwnProperty('_priority')){
				let priority=0;
				if(info.priority){
					priority=info.priority*100;
				}
				if(info.silent){
					priority++;
				}
				if(info.equipSkill) priority-=25;
				if(info.cardSkill) priority-=50;
				if(info.ruleSkill) priority-=75;
				info._priority=priority;
			}
			if(i[0]=='_') game.addGlobalSkill(i);
		},
		finishCards:()=>{
			_status.cardsFinished=true;
			const mode=get.mode(),filterTarget=(card,player,target)=>player==target&&target.canEquip(card,true),aiBasicOrder=(card,player)=>{
				const equipValue=get.equipValue(card,player)/20;
				return player&&player.hasSkillTag('reverseEquip')?8.5-equipValue:8+equipValue;
			},aiBasicValue=(card,player,index,method)=>{
				if(!player.getCards('e').contains(card)&&!player.canEquip(card,true)) return 0.01;
				const info=get.info(card),current=player.getEquip(info.subtype),value=current&&card!=current&&get.value(current,player);
				let equipValue=info.ai.equipValue||info.ai.basic.equipValue;
				if(typeof equipValue=='function'){
					if(method=='raw')return equipValue(card,player);
					if(method=='raw2')return equipValue(card,player)-value;
					return Math.max(0.1,equipValue(card,player)-value);
				}
				if(typeof equipValue!='number') equipValue=0;
				if(method=='raw') return equipValue;
				if(method=='raw2') return equipValue-value;
				return Math.max(0.1,equipValue-value);
			},aiResultTarget=(player,target,card)=>get.equipResult(player,target,card.name);
			Object.keys(lib.card).forEach(libCardKey=>{
				const info = `${libCardKey}_info`;
				if(lib.translate[`${info}_${mode}`]) lib.translate[info]=lib.translate[`${info}_${mode}`];
				else if(lib.translate[`${info}_zhu`]&&(mode=='identity'||mode=='guozhan'&&_status.mode=='four')) lib.translate[info]=lib.translate[`${info}_zhu`];
				else if(lib.translate[`${info}_combat`]&&get.is.versus()) lib.translate[info]=lib.translate[`${info}_combat`];
				const card=lib.card[libCardKey];
				if(card.filterTarget&&card.selectTarget==undefined) card.selectTarget=1;
				if(card.autoViewAs){
					if(!card.ai) card.ai={};
					if(!card.ai.order){
						card.ai.order=lib.card[card.autoViewAs].ai.order;
						if(!card.ai.order&&lib.card[card.autoViewAs].ai.basic) card.ai.order=lib.card[card.autoViewAs].ai.basic.order;
					}
				}
				if(card.type=='equip'){
					if(card.enable==undefined) card.enable=true;
					if(card.selectTarget==undefined) card.selectTarget=-1;
					if(card.filterTarget==undefined) card.filterTarget=filterTarget;
					if(card.modTarget==undefined) card.modTarget=true;
					if(card.allowMultiple==undefined) card.allowMultiple=false;
					if(card.content==undefined) card.content=lib.element.content.equipCard;
					if(card.toself==undefined) card.toself=true;
					if(card.ai==undefined) card.ai={
						basic:{}
					};
					if(card.ai.basic==undefined) card.ai.basic={};
					if(card.ai.result==undefined) card.ai.result={
						target:1.5
					};
					if(card.ai.basic.order==undefined) card.ai.basic.order=aiBasicOrder;
					if(card.ai.basic.useful==undefined) card.ai.basic.useful=2;
					if(card.subtype=='equip3'){
						if(card.ai.basic.equipValue==undefined) card.ai.basic.equipValue=7;
					}
					else if(card.subtype=='equip4'){
						if(card.ai.basic.equipValue==undefined) card.ai.basic.equipValue=4;
					}
					else if(card.ai.basic.equipValue==undefined) card.ai.basic.equipValue=1;
					if(card.ai.basic.value==undefined) card.ai.basic.value=aiBasicValue;
					if(!card.ai.result.keepAI) card.ai.result.target=aiResultTarget;
				}
				else if(card.type=='delay'){
					if(card.enable==undefined) card.enable=true;
					if(card.filterTarget==undefined) card.filterTarget=lib.filter.judge;
					if(card.content==undefined) card.content=lib.element.content.addJudgeCard;
					if(card.allowMultiple==undefined) card.allowMultiple=false;
				}
			});
			Object.keys(lib.skill).forEach(value=>game.finishSkill(value));
		},
		checkMod:function(){
			const argumentArray=Array.from(arguments),name=argumentArray[argumentArray.length-2];
			let skills=argumentArray[argumentArray.length-1];
			if(skills.getSkills) skills=skills.getModableSkills(_status.event.useCache === true);
			const arg=argumentArray.slice(0,-2);
			skills.forEach(value=>{
				var mod = get.info(value).mod[name];
				if(!mod)return;
				const result=mod.apply(this,arg);
				if(typeof arg[arg.length-1]!='object'&&result!=undefined) arg[arg.length-1]=result;
			});
			return arg[arg.length-1];
		},
		prepareArena:num=>{
			_status.prepareArena=true;
			game.showHistory(false);
			ui.create.players(num);
			ui.create.me();
			ui.create.cardsAsync();
			game.finishCards();
		},
		clearArena:()=>{
			ui.control.innerHTML='';
			ui.arenalog.innerHTML='';
			Array.from(ui.arena.childNodes).forEach(value=>{
				if(value==ui.canvas) return;
				if(value==ui.control) return;
				if(value==ui.arenalog) return;
				if(value==ui.roundmenu) return;
				if(value==ui.timer) return;
				if(value==ui.autonode) return;
				value.remove();
			});
			ui.sidebar.innerHTML='';
			ui.cardPile.innerHTML='';
			ui.discardPile.innerHTML='';
			ui.special.innerHTML='';
			ui.ordering.innerHTML='';
			ui.playerids.remove();
			game.players.length=0;
			game.dead.length=0;
			game.me=null;
		},
		clearConnect:()=>{
			if(ui.ipnode){
				ui.ipnode.remove();
				delete ui.ipnode;
			}
			if(ui.iptext){
				ui.iptext.remove();
				delete ui.iptext;
			}
			if(ui.ipbutton){
				ui.ipbutton.remove();
				delete ui.ipbutton;
			}
			if(ui.recentIP){
				ui.recentIP.remove();
				delete ui.recentIP;
			}
			if(ui.hall_button){
				ui.hall_button.remove();
				delete ui.hall_button;
			}
			if(ui.startServer){
				ui.startServer.remove();
				delete ui.startServer;
			}
			if(ui.rooms){
				ui.rooms.forEach(value=>value.remove());
				delete ui.rooms;
			}
			if(ui.roombase){
				ui.roombase.remove();
				delete ui.roombase;
			}
			if(!ui.connectEvents) return;
			ui.connectEvents.remove();
			ui.connectEventsCount.remove();
			ui.connectClients.remove();
			ui.connectClientsCount.remove();
			ui.createRoomButton.remove();
			delete ui.connectEvents;
			delete ui.connectEventsCount;
			delete ui.connectClients;
			delete ui.connectClientsCount;
			delete ui.createRoomButton;
		},
		log:function(){
			let str='',str2='',logvid=null;
			const color=new Map([
				['b','blue'],
				['y','yellow'],
				['g','green']
			]);
			Array.from(arguments).forEach(value=>{
				const itemtype=get.itemtype(value);
				if(itemtype=='player'||itemtype=='players'){
					str+=`<span class="bluetext">${get.translation(value)}</span>`;
					str2+=get.translation(value);
				}
				else if(itemtype=='cards'||itemtype=='card'||(typeof value=='object'&&value&&value.name)){
					str+=`<span class="yellowtext">${get.translation(value)}</span>`;
					str2+=get.translation(value);
				}
				else if(typeof value=='object'){
					if(value.parentNode==ui.historybar) logvid=value.logvid;
					else{
						str+=get.translation(value);
						str2+=get.translation(value);
					}
				}
				else if(typeof value=='string'){
					if(value[0]=='【'&&value[value.length-1]=='】'){
						str+=`<span class="greentext">${get.translation(value)}</span>`;
						str2+=get.translation(value);
					}
					else if(value[0]=='#'){
						str+=`<span class="${color.get(value[1])||''}text">${get.translation(value.slice(2))}</span>`;
						str2+=get.translation(value.slice(2));
					}
					else{
						str+=get.translation(value);
						str2+=get.translation(value);
					}
				}
				else{
					str+=value;
					str2+=value;
				}
			});
			const node=ui.create.div();
			node.innerHTML=lib.config.log_highlight?str:str2;
			ui.sidebar.insertBefore(node,ui.sidebar.firstChild);
			game.addVideo('log',null,lib.config.log_highlight?str:str2);
			game.broadcast((str,str2)=>game.log(lib.config.log_highlight?str:str2),str,str2);
			if(!_status.video&&!game.online){
				if(logvid) game.logv(logvid,`<div class="text center">${lib.config.log_highlight?str:str2}</div>`);
				else logvid=_status.event.getLogv();
			}
			if(lib.config.show_log=='off'||game.chess) return;
			const nodeentry=node.cloneNode(true);
			ui.arenalog.insertBefore(nodeentry,ui.arenalog.firstChild);
			if(!lib.config.clear_log) while(ui.arenalog.childNodes.length&&ui.arenalog.scrollHeight>ui.arenalog.offsetHeight){
				ui.arenalog.lastChild.remove();
			}
			if(!lib.config.low_performance){
				nodeentry.style.transition='all 0s';
				nodeentry.style.marginBottom=`-${nodeentry.offsetHeight}px`;
				ui.refresh(nodeentry);
				nodeentry.style.transition='';
				nodeentry.style.marginBottom='';
			}
			if(!lib.config.clear_log) return;
			nodeentry.timeout=setTimeout(()=>nodeentry.delete(),1000);
			Array.from(ui.arenalog.childNodes).forEach(value=>{
				if(!value.timeout) value.remove();
			});
		},
		logv:(player,card,targets,event,forced,logvid)=>{
			if(!player){
				player=_status.event.getParent().logvid;
				if(!player) return;
			}
			const node=ui.create.div('.hidden');
			node.node={};
			logvid=logvid||get.id();
			game.broadcast(game.logv,player,card,targets,event,forced,logvid);
			if(typeof player=='string'){
				const childNode=Array.from(ui.historybar.childNodes).find(value=>value.logvid==player);
				if(childNode) childNode.added.push(card);
				return;
			}
			if(typeof card=='string'){
				if(card!='die'){
					if(lib.skill[card]&&lib.skill[card].logv===false&&!forced) return;
					if(!lib.translate[card]) return;
				}
				let avatar;
				if(!player.isUnseen(0)) avatar=player.node.avatar.cloneNode();
				else if(!player.isUnseen(1)) avatar=player.node.avatar2.cloneNode();
				else return;
				node.node.avatar=avatar;
				avatar.style.transform='';
				avatar.className='avatar';
				if(card=='die'){
					node.dead=true;
					node.player=player;
					const avatar2=avatar.cloneNode();
					avatar2.className='avatarbg grayscale1';
					avatar.appendChild(avatar2);
					avatar.style.opacity=0.6;
				}
				else{
					node.node.text=ui.create.div('',get.translation(card,'skill'),avatar);
					node.node.text.dataset.nature='water';
					node.skill=card;
				}
				node.appendChild(avatar);
				if(card=='die'&&targets&&targets!=player){
					node.source=targets;
					player=targets;
					if(!player.isUnseen(0)) avatar=player.node.avatar.cloneNode();
					else if(!player.isUnseen(1)) avatar=player.node.avatar2.cloneNode();
					else if(get.mode()=='guozhan'&&player.node&&player.node.name_seat){
						avatar=ui.create.div('.avatar.cardbg');
						avatar.innerHTML=player.node.name_seat.innerHTML[0];
					}
					else return;
					avatar.style.transform='';
					node.node.avatar2=avatar;
					avatar.classList.add('avatar2');
					node.appendChild(avatar);
				}
			}
			else if(Array.isArray(card)){
				node.cards=card[1].slice(0)
				card=card[0];
				const info=[card.suit||'',card.number||'',card.name||'',card.nature||''];
				if(!Array.isArray(node.cards)||!node.cards.length) node.cards=[ui.create.card(node,'noclick',true).init(info)];
				if(card.name=='wuxie'){
					if(ui.historybar.firstChild&&ui.historybar.firstChild.type=='wuxie'){
						ui.historybar.firstChild.players.push(player);
						ui.historybar.firstChild.cards.addArray(node.cards);
						return;
					}
					node.type='wuxie';
					node.players=[player];
				}
				if(card.copy) card.copy(node,false);
				else{
					card=ui.create.card(node,'noclick',true);
					card.init(info);
				}
				let avatar;
				if(!player.isUnseen(0)) avatar=player.node.avatar.cloneNode();
				else if(!player.isUnseen(1)) avatar=player.node.avatar2.cloneNode();
				else if(get.mode()=='guozhan'&&player.node&&player.node.name_seat){
					avatar=ui.create.div('.avatar.cardbg');
					avatar.innerHTML=player.node.name_seat.innerHTML[0];
				}
				else return;
				node.node.avatar=avatar;
				avatar.style.transform='';
				avatar.classList.add('avatar2');
				node.appendChild(avatar);
				if(targets&&targets.length==1&&targets[0]!=player&&get.itemtype(targets[0])=='player') (()=>{
					let avatar2;
					const target=targets[0];
					if(!target.isUnseen(0)) avatar2=target.node.avatar.cloneNode();
					else if(!player.isUnseen(1)) avatar2=target.node.avatar2.cloneNode();
					else if(get.mode()=='guozhan'&&target.node&&target.node.name_seat){
						avatar2=ui.create.div('.avatar.cardbg');
						avatar2.innerHTML=target.node.name_seat.innerHTML[0];
					}
					else return;
					node.node.avatar2=avatar2;
					avatar2.style.transform='';
					avatar2.classList.add('avatar2');
					avatar2.classList.add('avatar3');
					node.insertBefore(avatar2,avatar);
				})();
			}
			if(targets&&targets.length){
				if(targets.length==1&&targets[0]==player){
					node.targets=[];
				}
				else{
					node.targets=targets;
				}
			}
			const fullheight=ui.historybar.offsetHeight,num=Math.round((fullheight-8)/50),margin=(fullheight-42*num)/(num+1);
			node.style.transform='scale(0.8)';
			ui.historybar.insertBefore(node,ui.historybar.firstChild);
			ui.refresh(node);
			node.classList.remove('hidden');
			Array.from(ui.historybar.childNodes).forEach((value,index)=>{
				if(index<num){
					value.style.transform=`scale(1) translateY(${margin+index*(42+margin)-4}px)`;
					return;
				}
				if(value.removetimeout) return;
				value.style.opacity=0;
				value.style.transform=`scale(1) translateY(${fullheight}px)`;
				value.removetimeout=setTimeout((current=>()=>current.remove())(value),500);
			});
			if(lib.config.touchscreen) node.addEventListener('touchstart',ui.click.intro);
			else{
				node.addEventListener(lib.config.pop_logv?'mousemove':'click',ui.click.logv);
				node.addEventListener('mouseleave',ui.click.logvleave);
			}
			node.logvid=logvid;
			node.added=[];
			if(!game.online){
				event=event||_status.event;
				event.logvid=node.logvid;
			}
			return node;
		},
		putDB:(storeName,idbValidKey,value,onSuccess,onError)=>{
			if(!lib.db) return Promise.resolve(value);
			if(lib.status.reload) return new Promise((resolve,reject)=>lib[_status.dburgent?'ondb2':'ondb'].push(['putDB',[storeName,idbValidKey,value,event=>{
				if(typeof onSuccess=='function') onSuccess(event);
				resolve(event);
			},event=>{
				if(typeof onError=='function'){
					onError(event);
					resolve();
				}
				else reject(event);
			}]]));
			lib.status.reload++;
			return new Promise((resolve,reject)=>{
				const record=lib.db.transaction([storeName],'readwrite').objectStore(storeName).put(value,idbValidKey);
				record.onerror=event=>{
					if(typeof onError=='function'){
						onError(event);
						game.reload2();
						resolve();
					}
					else{
						game.reload2();
						reject(event);
					}
				};;
				record.onsuccess=event=>{
					if(typeof onSuccess=='function'){
						_status.dburgent=true;
						onSuccess(event);
						delete _status.dburgent;
					}
					game.reload2();
					resolve(event);
				};
			});
		},
		getDB:(storeName,query,onSuccess,onError)=>{
			if(!lib.db) return new Promise(resolve=>{
				if(typeof onSuccess=='function') onSuccess(null);
				resolve(null);
			});
			if(lib.status.reload) return new Promise((resolve,reject)=>lib[_status.dburgent?'ondb2':'ondb'].push(['getDB',[storeName,query,result=>{
				if(typeof onSuccess=='function') onSuccess(result);
				resolve(result);
			},event=>{
				if(typeof onError=='function'){
					onError(event);
					resolve();
				}
				else reject(event);
			}]]));
			return new Promise(query?(resolve,reject)=>{
				lib.status.reload++;
				const idbRequest=lib.db.transaction([storeName],'readwrite').objectStore(storeName).get(query);
				idbRequest.onerror=event=>{
					if(typeof onError=='function'){
						onError(event);
						game.reload2();
						resolve();
					}
					else{
						game.reload2();
						reject(event);
					}
				};;
				idbRequest.onsuccess=event=>{
					const result=event.target.result;
					if(typeof onSuccess=='function'){
						_status.dburgent=true;
						onSuccess(result);
						delete _status.dburgent;
					}
					game.reload2();
					resolve(result);
				};
			}:(resolve,reject)=>{
				lib.status.reload++;
				const idbRequest=lib.db.transaction([storeName],'readwrite').objectStore(storeName).openCursor(),object={};
				idbRequest.onerror=event=>{
					if(typeof onError=='function'){
						onError(event);
						game.reload2();
						resolve();
					}
					else{
						game.reload2();
						reject(event);
					}
				};;
				idbRequest.onsuccess=event=>{
					const result=event.target.result;
					if(result){
						object[result.key]=result.value;
						result.continue();
						return;
					}
					if(typeof onSuccess=='function'){
						_status.dburgent=true;
						onSuccess(object);
						delete _status.dburgent;
					}
					game.reload2();
					resolve(object);
				};
			});
		},
		deleteDB:(storeName,query,onSuccess,onError)=>{
			if(!lib.db) return new Promise(resolve=>{
				if(typeof onSuccess=='function') onSuccess(false);
				resolve(false);
			});
			if(lib.status.reload) return new Promise((resolve,reject)=>lib[_status.dburgent?'ondb2':'ondb'].push(['deleteDB',[storeName,query,event=>{
				if(typeof onSuccess=='function') onSuccess(event);
				resolve(event);
			},event=>{
				if(typeof onError=='function'){
					onError(event);
					resolve();
				}
				else reject(event);
			}]]));
			return query?new Promise((resolve,reject)=>{
				lib.status.reload++;
				const record=lib.db.transaction([storeName],'readwrite').objectStore(storeName).delete(query);
				record.onerror=event=>{
					if(typeof onError=='function'){
						onError(event);
						game.reload2();
						resolve();
					}
					else{
						game.reload2();
						reject(event);
					}
				};
				record.onsuccess=event=>{
					if(typeof onSuccess=='function') onSuccess(event);
					game.reload2();
					resolve(event);
				};
			}):game.getDB(storeName).then(object=>{
				const keys=Object.keys(object);
				lib.status.reload+=keys.length;
				const store=lib.db.transaction([storeName],'readwrite').objectStore(storeName);
				return Promise.allSettled(keys.map(key=>new Promise((resolve,reject)=>{
					const request=store.delete(key);
					request.onerror=event=>{
						game.reload2();
						reject(event);
					};;
					request.onsuccess=event=>{
						game.reload2();
						resolve(event);
					};
				})));
			});
		},
		save:(key,value,mode)=>{
			if(_status.reloading) return;
			mode=mode||lib.config.mode;
			if(lib.db){
				if(!key){
					game.putDB('data',mode,get.copy(lib.storage));
					return;
				}
				if(mode==lib.config.mode){
					if(value==undefined) delete lib.storage[key];
					else lib.storage[key]=value;
					lib.storage.version=lib.version;
					game.putDB('data',mode,lib.storage);
				}
				else game.getDB('data',mode,config=>{
					if(!config) config={};
					if(value==undefined) delete config[key];
					else config[key]=value;
					config.version=lib.version;
					game.putDB('data',mode,config);
				});
				return;
			}
			if(!key){
				localStorage.setItem(`${lib.configprefix}${mode}`,JSON.stringify(lib.storage));
				return;
			}
			let config;
			try{
				config=JSON.parse(localStorage.getItem(`${lib.configprefix}${mode}`));
				if(typeof config!='object') throw 'err';
			}
			catch(err){
				config={};
			}
			if(value==undefined){
				delete config[key];
				if(mode==lib.config.mode) delete lib.storage[key];
			}
			else{
				config[key]=value;
				if(mode==lib.config.mode) lib.storage[key]=value;
			}
			config.version=lib.version;
			localStorage.setItem(`${lib.configprefix}${mode}`,JSON.stringify(config));
		},
		showChangeLog:()=>{
			if(lib.version==lib.config.version&&!_status.extensionChangeLog) return;
			const ul=document.createElement('ul');
			ul.style.textAlign='left';
			const caption=lib.version==lib.config.version?'扩展更新':`${lib.version}更新内容`;
			let players=null,cards=null;
			if(lib.version!=lib.config.version) lib.changeLog.forEach(value=>{
				if(value.startsWith('players://')) try{
					players=JSON.parse(value.slice(10)).filter(value=>lib.character[value]);
				}
				catch(e){
					players=null;
				}
				else if(value.startsWith('cards://')) try{
					cards=JSON.parse(value.slice(8)).filter(value=>lib.card[value]);
				}
				catch(e){
					cards=null;
				}
				else{
					const li=document.createElement('li');
					li.innerHTML=value;
					ul.appendChild(li);
				}
			});
			game.saveConfig('version',lib.version);
			if(_status.extensionChangeLog) Object.keys(_status.extensionChangeLog).forEach(value=>{
				const li=document.createElement('li');
				li.innerHTML=`${value}:${_status.extensionChangeLog[value]}`;
				ul.appendChild(li);
			});
			const dialog=ui.create.dialog(caption,'hidden'),lic=ui.create.div(dialog.content);
			lic.style.display='block';
			ul.style.display='inline-block';
			ul.style.marginLeft='-40px';
			lic.appendChild(ul);
			if(players&&players.length){
				dialog.addSmall([players,'character']);
				dialog.classList.add('forcebutton');
				dialog.classList.add('withbg');
			}
			if(cards&&cards.length){
				dialog.addSmall([cards.map(value=>[get.translation(get.type(value)),'',value]),'vcard']);
				dialog.classList.add('forcebutton');
				dialog.classList.add('withbg');
			}
			dialog.open();
			let hidden=false;
			if(!ui.auto.classList.contains('hidden')){
				ui.auto.hide();
				hidden=true;
			}
			game.pause();
			const control=ui.create.control('确定',()=>{
				dialog.close();
				control.close();
				if(hidden) ui.auto.show();
				game.resume();
			});
			lib.init.onfree();
		},
		showExtensionChangeLog:(str,extname)=>{
			extname=extname||_status.extension;
			const cfg=`extension_${extname}_changelog`;
			if(!lib.extensionPack[extname]||lib.extensionPack[extname].version==lib.config[cfg]) return;
			game.saveConfig(cfg,lib.extensionPack[extname].version);
			if(_status.extensionChangeLog) return;
			_status.extensionChangeLog={};
			_status.extensionChangeLog[extname]=str;
		},
		saveConfig:(key,value,local,callback)=>{
			if(_status.reloading) return;
			if(local){
				const localmode=typeof local=='string'?local:lib.config.mode;
				if(!lib.config.mode_config[localmode]) lib.config.mode_config[localmode]={};
				if(value==undefined) delete lib.config.mode_config[localmode][key];
				else lib.config.mode_config[localmode][key]=value;
				key+=`_mode_config_${localmode}`;
			}
			else if(value==undefined) delete lib.config[key];
			else lib.config[key]=value;
			if(lib.db){
				if(value==undefined) game.deleteDB('config',key,callback);
				else game.putDB('config',key,value,callback);
				return;
			}
			let config;
			try{
				config=JSON.parse(localStorage.getItem(`${lib.configprefix}config`));
				if(!config||typeof config!='object') throw 'err';
			}
			catch(err){
				config={};
			}
			if(value===undefined) delete config[key];
			else config[key]=value;
			localStorage.setItem(`${lib.configprefix}config`,JSON.stringify(config));
			if(callback) callback();
		},
		saveConfigValue:key=>game.saveConfig(key,lib.config[key]),
		saveExtensionConfig:(extension,key,value)=>game.saveConfig(`extension_${extension}_${key}`,value),
		saveExtensionConfigValue:(extension,key)=>game.saveExtensionConfig(extension,key,game.getExtensionConfig(extension,key)),
		getExtensionConfig:(extension,key)=>lib.config[`extension_${extension}_${key}`],
		clearModeConfig:mode=>{
			if(_status.reloading) return;
			if(lib.db){
				game.getDB('config',null,config=>Object.keys(config).forEach(value=>{
					if(value.substr(value.indexOf('_mode_config')+13)==mode) game.saveConfig(value);
				}));
				return;
			}
			let config;
			try{
				config=JSON.parse(localStorage.getItem(`${lib.configprefix}config`));
				if(!config||typeof config!='object') throw 'err';
			}
			catch(err){
				config={};
			}
			Object.keys(config).forEach(value=>{
				if(value.substr(value.indexOf('_mode_config')+13)==mode) delete config[value];
			});
			localStorage.setItem(`${lib.configprefix}config`,JSON.stringify(config));
			localStorage.removeItem(`${lib.configprefix}${mode}`);
		},
		addPlayer:(position,character,character2)=>{
			if(position<0||position>game.players.length+game.dead.length||position==undefined) position=Math.ceil(Math.random()*(game.players.length+game.dead.length));
			const players=game.players.concat(game.dead);
			ui.arena.setNumber(players.length+1);
			players.forEach(value=>{
				if(parseInt(value.dataset.position)>=position) value.dataset.position=parseInt(value.dataset.position)+1;
			});
			const player=ui.create.player(ui.arena).animate('start');
			if(character) player.init(character,character2);
			game.players.push(player);
			player.dataset.position=position;
			game.arrangePlayers();
			return player;
		},
		addFellow:(position,character,animation)=>{
			game.addVideo('addFellow',null,[position,character,animation]);
			const player=ui.create.player(ui.arena).animate(animation||'start');
			player.dataset.position=position||game.players.length+game.dead.length;
			player.getId();
			if(character) player.init(character);
			game.players.push(player);
			game.arrangePlayers();
			return player;
		},
		triggerEnter:player=>{
			const next=game.createEvent('enterGame',false);
			next.player=player;
			next.setContent(()=>{
				event.trigger('enterGame');
			});
			return next;
		},
		restorePlayer:player=>{
			if(game.players.contains(player)||game.dead.contains(player)) return;
			let position=parseInt(player.dataset.position);
			if(position<0||position>game.players.length+game.dead.length||position==undefined) position=Math.ceil(Math.random()*(game.players.length+game.dead.length));
			const players=game.players.concat(game.dead);
			ui.arena.setNumber(players.length+1);
			players.forEach(value=>{
				if(parseInt(value.dataset.position)>=position) value.dataset.position=parseInt(value.dataset.position)+1;
			});
			game.players.push(player);
			delete player.removed;
			player.removeAttribute('style');
			player.animate('start');
			ui.arena.appendChild(player);
			game.arrangePlayers();
			return player;
		},
		removePlayer:player=>{
			if(_status.roundStart==player) _status.roundStart=player.next||player.getNext()||game.players[0];
			const players=game.players.concat(game.dead);
			player.style.left=`${player.getLeft()}px`;
			player.style.top=`${player.getTop()}px`;
			if(player==undefined) player=game.dead[0]||game.me.next;
			const position=parseInt(player.dataset.position);
			players.forEach(value=>{
				if(parseInt(value.dataset.position)>position) value.dataset.position=parseInt(value.dataset.position)-1;
			});
			if(player.isAlive()){
				player.next.previous=player.previous;
				player.previous.next=player.next;
			}
			player.nextSeat.previousSeat=player.previousSeat;
			player.previousSeat.nextSeat=player.nextSeat;
			player.delete();
			game.players.remove(player);
			game.dead.remove(player);
			ui.arena.setNumber(players.length-1);
			player.removed=true;
			if(player==game.me){
				ui.me.hide();
				ui.auto.hide();
				ui.wuxie.hide();
			}
			setTimeout(()=>player.removeAttribute('style'),500);
			return player;
		},
		replacePlayer:(player,character,character2)=>{
			player.removed=true;
			const position=parseInt(player.dataset.position);
			game.players.remove(player);
			game.dead.remove(player);
			player.delete();
			const player2=ui.create.player(ui.arena).animate('start');
			if(character) player2.init(character,character2);
			game.players.push(player2);
			player2.dataset.position=position;
			player2.nextSeat=player.nextSeat;
			player2.previousSeat=player.previousSeat;
			player2.nextSeat.previousSeat=player2;
			player2.previousSeat.nextSeat=player2;
			const player3=player2.nextSeat;
			while(player3.isDead()){
				player3=player3.nextSeat;
			}
			player3.previous=player2;
			player2.next=player3;
			const player4=player2.previousSeat;
			while(player4.isDead()){
				player4=player4.previousSeat;
			}
			player4.next=player2;
			player2.previous=player4;
			if(_status.roundStart==player) _status.roundStart=player2;
			return player2;
		},
		arrangePlayers:()=>{
			if(game.chess&&game.me){
				let friendCount=0,enemyCount=0;
				const rand=Math.random()<0.5,sortCount=new Map();
				game.players.forEach(value=>{
					if(value.side==game.me.side){
						if(rand) if(value==game.friendZhu) sortCount.set(value,-2);
						else sortCount.set(value,2*friendCount);
						else if(value==game.friendZhu) sortCount.set(value,-1);
						else sortCount.set(value,2*friendCount+1);
						friendCount++;
						return;
					}
					if(rand) if(value==game.enemyZhu) sortCount.set(value,-1);
					else sortCount.set(value,2*enemyCount+1);
					else if(value==game.enemyZhu) sortCount.set(value,-2);
					else sortCount.set(value,2*enemyCount);
					enemyCount++;
				});
				game.players.sort((a,b)=>sortCount.get(a)-sortCount.get(b));
			}
			else game.players.sort(lib.sort.position);
			game.players.concat(game.dead).sort(lib.sort.position).forEach((value,index,array)=>{
				if(index==0) value.previousSeat=array[array.length-1];
				else value.previousSeat=array[index-1];
				if(index==array.length-1) value.nextSeat=array[0];
				else value.nextSeat=array[index+1];
			});
			game.players.forEach((value,index,array)=>{
				if(index==0) value.previous=array[array.length-1];
				else value.previous=array[index-1];
				if(index==array.length-1) value.next=array[0];
				else value.next=array[index+1];
			});
		},
		filterSkills:(skills,player,exclude)=>{
			const out=skills.slice().removeArray(Object.keys(player.disabledSkills));
			if(!player.storage.skill_blocker||!player.storage.skill_blocker.length) return out;
			return out.filter(value=>exclude&&exclude.includes(value)||!get.is.blocked(value,player));
		},
		expandSkills:skills=>skills.addArray(skills.reduce((previousValue,currentValue)=>{
			const info=get.info(currentValue);
			if(info){
				if(Array.isArray(info.group)) previousValue.push(...info.group);
				else if(info.group) previousValue.push(info.group);
			}
			else console.log(currentValue);
			return previousValue;
		},[])),
		css:style=>Object.keys(style).forEach(value=>{
			let uiStyle=ui.style[value];
			if(!uiStyle){
				uiStyle=ui.style[value]=document.createElement('style');
				document.head.appendChild(uiStyle);
			}
			uiStyle.innerHTML=`${value}${JSON.stringify(style[value]).replace(/"/g,"")}`;
		}),
		hasPlayer:(func,includeOut)=>game.players.some(value=>(includeOut||!value.isOut())&&func(value)),
		hasPlayer2:(func,includeOut)=>game.players.concat(game.dead).some(value=>(includeOut||!value.isOut())&&func(value)),
		countPlayer:(func,includeOut)=>{
			if(typeof func!='function') func=lib.filter.all;
			return game.players.reduce((previousValue,currentValue)=>{
				if(!includeOut&&currentValue.isOut()) return previousValue;
				const result=func(currentValue);
				if(typeof result=='number') previousValue+=result;
				else if(result) previousValue++;
				return previousValue;
			},0);
		},
		countPlayer2:(func,includeOut)=>{
			if(typeof func!='function') func=lib.filter.all;
			return game.players.concat(game.dead).reduce((previousValue,currentValue)=>{
				if(!includeOut&&currentValue.isOut()) return previousValue;
				const result=func(currentValue);
				if(typeof result=='number') previousValue+=result;
				else if(result) previousValue++;
				return previousValue;
			},0);
		},
		filterPlayer:(func,list,includeOut)=>{
			if(!Array.isArray(list)) list=[];
			if(typeof func!='function') func=lib.filter.all;
			return list.addArray(game.players.filter(value=>(includeOut||!value.isOut())&&func(value)));
		},
		filterPlayer2:(func,list,includeOut)=>{
			if(!Array.isArray(list)) list=[];
			if(typeof func!='function') func=lib.filter.all;
			return list.addArray(game.players.concat(game.dead).filter(value=>(includeOut||!value.isOut())&&func(value)));
		},
		findPlayer:(func,includeOut)=>game.players.find(value=>(includeOut||!value.isOut())&&func(value))||null,
		findPlayer2:(func,includeOut)=>game.players.concat(game.dead).find(value=>(includeOut||!value.isOut())&&func(value))||null,
		findCards:(func,all)=>Object.keys(lib.card).filter(value=>{
			if(!lib.translate[`${value}_info`]) return false;
			if(lib.card[value].mode&&lib.card[value].mode.includes(lib.config.mode)==false) return false;
			if(!all&&!lib.inpile.includes(value)) return false;
			return func(value,lib.card[value]);
		}),
		countGroup:()=>{
			const list=lib.group.slice(0);
			return game.countPlayer(current=>{
				if(!list.includes(current.group)) return false;
				list.remove(current.group);
				return true;
			});
		},
		players:[],
		dead:[],
		imported:[],
		playerMap:{},
		phaseNumber:0,
		roundNumber:0,
		shuffleNumber:0,
	};
	window['b'+'ann'+'e'+'dE'+'x'+'ten'+'s'+'i'+'o'+'ns']=['\u4fa0\u4e49','\u5168\u6559\u7a0b'];
	const ui={
		updates:[],
		thrown:[],
		touchlines:[],
		todiscard:{},
		refresh:function(node){
			void window.getComputedStyle(node, null).getPropertyValue("opacity");
		},
		create:{
			/**
			 * 创建codemirror编辑器
			 * @param {HTMLDivElement} container 
			 * @param {Function} saveInput 
			 */
			editor:function(container,saveInput){
				const createList=[];
				const containerDelete=container.delete;
				const editorpage=ui.create.div(container);
				//删除container的时候,删除创建的ul列表
				container.delete=function(){
					for (let i=createList.length-1;i>=0;i--){
						createList[i].parentNode&&createList[i].parentNode.removeChild(createList[i]);
					}
					Array.from(editorpage.children).forEach(v=>{v.style.background=''});
					containerDelete.apply(this, arguments);
				}
				//创建ul列表
				const createMenu=function(pos,self,List,click){
					if(!self||self==window) return;
					const parent=self.parentNode;
					if (parent){
						for(let i=0;i<parent.childElementCount;i++){
							const node=parent.childNodes[i];
							if(node!=self&&node.ul) closeMenu.call(node);
						}
					}
					if(self.ul){
						self.style.background='#08f';
						createList.add(self.ul);
						ui.window.appendChild(self.ul);
						return self.ul;
					}
					const editor=container.editor;
					if(!editor) return false;
					self.style.background='#08f';
					const ul=document.createElement('ul');
					container.css.call(ul,{
						position:'absolute',
						top:pos.bottom/game.documentZoom+'px',
						left: pos.left/game.documentZoom+'px',
						height:'20em',
						width:pos.width*4/game.documentZoom+'px',
						//'font-family':'shousha',
						'font-size':(lib.config.codeMirror_fontSize?lib.config.codeMirror_fontSize.slice(0,-2):16)/game.documentZoom+'px',
						
					});
					const theme=editor.options.theme;
					lib.setScroll(ul);
					lib.setMousewheel(ul);
					ul.className="CodeMirror-hints "+theme;
					const getActive=()=>{
						let i=0;
						while(i<ul.childElementCount){
							if(ul.childNodes[i].classList.contains('CodeMirror-hint-active')) break;
							else i++;
						}
						return i;
					};
					const setActive=i=>{
						ul.childNodes[getActive()].classList.remove('CodeMirror-hint-active');
						ul.childNodes[i].classList.add('CodeMirror-hint-active');
						return i;
					};
					if (List&&List.length&&click) {
						for(let i=0;i<List.length;++i) {
							const elt=ul.appendChild(document.createElement("li"));
							elt.style.color='black';
							elt.style.boxShadow='none';
							const cur=List[i];
							if(cur instanceof HTMLElement){
								elt.appendChild(cur);
							}else{
								elt.innerHTML=cur;
							}
							let className="CodeMirror-hint"+(i!=0?"":" "+"CodeMirror-hint-active");
							if(cur.className!=null) className=cur.className+" "+className;
							elt.className=className;
							elt.hintId=i;
							ui.window.listen.call(elt,function(){
								setActive(this.hintId);
								this.focus();
								click.call(this);
							});
							elt.onmousemove=elt.ontouchstart=()=>{
								setActive(i);
							};
						}
					}
					createList.add(ul);
					ui.window.appendChild(ul);
					return ul;
				};
				//关闭ul列表
				const closeMenu=function(){
					const ul=this.ul;
					if(!ul) return false;
					if(ul.parentNode) ul.parentNode.removeChild(ul);
					this.style.background='';
					//创建后不用删除了,除非以后要动态加载。
					//delete this.ul;
					createList.remove(ul);
					return ul;
				};
				const discardConfig=ui.create.div('.editbutton','取消',editorpage,function(){
					ui.window.classList.remove('shortcutpaused');
					ui.window.classList.remove('systempaused');
					container.delete(null);
					delete window.saveNonameInput;
				});
				const saveConfig=ui.create.div('.editbutton','保存',editorpage,saveInput);
				const theme=ui.create.div('.editbutton','主题',editorpage,function(){
					if(!this||this==window) return;
					if(this.ul&&this.ul.parentNode){
						return closeMenu.call(this);
					}
					//this
					const self=this;
					if(!this.ul){
						//主题列表
						const list=['mdn-like','mbo'];
						//正在使用的主题
						const active=container.editor.options.theme;
						//排个序
						list.remove(active).splice(0,0,active);
						//元素位置
						const pos=self.getBoundingClientRect();
						//点击事件
						const click=function(e){
							const theme=this.innerHTML;
							container.editor.setOption("theme",theme);
							setTimeout(()=>container.editor.refresh(),0);
							game.saveConfig('codeMirror_theme',theme);
							closeMenu.call(self);
						};
						const ul=createMenu(pos,self,list,click);
						self.ul=ul;
					}else{
						createMenu(null,self);
					}
				});
				const edit=ui.create.div('.editbutton','编辑',editorpage,function(){
					if(!this||this==window) return;
					if(this.ul&&this.ul.parentNode){
						return closeMenu.call(this);
					}
					const self=this;
					if(!this.ul){
						const pos=this.getBoundingClientRect();
						const list=['撤销        Ctrl+Z', '恢复撤销    Ctrl+Y'];
						const click=function(e){
							const num=this.innerHTML.indexOf("Ctrl");
							const inner=this.innerHTML.slice(num).replace("+", "-");
							container.editor.execCommand(container.editor.options.extraKeys[inner]);
							setTimeout(()=>container.editor.refresh(),0);
							closeMenu.call(self);
						};
						const ul=createMenu(pos,self,list,click);
						this.ul=ul;
					}else{
						createMenu(null,self);
					}
				});
				const fontSize=ui.create.div('.editbutton','字号',editorpage,function(){
					if(!this||this==window) return;
					if(this.ul&&this.ul.parentNode){
						return closeMenu.call(this);
					}
					const self=this;
					if(!this.ul){
						const pos=this.getBoundingClientRect();
						const list=['16px','18px','20px','22px','24px','26px'];
						const click=function(e){
							const size=this.innerHTML;
							container.style.fontSize=size.slice(0,-2)/game.documentZoom+'px';
							Array.from(self.parentElement.children).map(v=>v.ul).filter(Boolean).forEach(v=>{v.style.fontSize=size.slice(0,-2)/game.documentZoom+'px'});
							setTimeout(()=>container.editor.refresh(),0);
							game.saveConfig('codeMirror_fontSize',size);
							closeMenu.call(self);
						};
						const ul=createMenu(pos,self,list,click);
						this.ul=ul;
					}else{
						createMenu(null,self);
					}
				});
				const editor=ui.create.div(editorpage);
				return editor;
			},
			cardTempName:function(card,applyNode){
				let getApplyNode=applyNode||card;
				let cardName=get.name(card);
				let cardNature=get.nature(card);
				let tempname=get.translation(cardName);
				let cardTempNameConfig=lib.config.cardtempname;
				let node=getApplyNode._tempName||ui.create.div('.tempname',getApplyNode);
				let datasetNature='';
				getApplyNode._tempName=node;
				if(cardTempNameConfig!='image'){
					//清空,避免和下面的image部分有冲突
					node.innerHTML='';
					datasetNature='fire';
					if(get.position(card)=='j'&&card.viewAs&&card.viewAs!=card.name) {
						datasetNature = 'wood';
						tempname=get.translation(card.viewAs);
					}else{
						if(cardName=='sha'){
							if(cardNature) tempname=get.translation(cardNature)+tempname;
							if(cardNature=='thunder') datasetNature='thunder';
							if(cardNature=='kami') datasetNature='kami';
							if(cardNature=='ice') datasetNature='ice';
						}
					}
					if(cardTempNameConfig=='default') getApplyNode._tempName.classList.add('vertical');
					if(datasetNature.length>0){
						node.dataset.nature=datasetNature;
					}else{
						delete node.dataset.nature;
						node.classList.add(datasetNature);
					}
				}else{
					if(get.position(card)=='j'&&card.viewAs&&card.viewAs!=card.name) {
						cardName=card.viewAs;
						tempname=get.translation(card.viewAs);
					}
					if(cardName=='sha'){
						if(cardNature) tempname=get.translation(cardNature)+tempname;
						if(cardNature=='fire') datasetNature = 'fire';
						if(cardNature=='thunder') datasetNature='thunder';
						if(cardNature=='kami') datasetNature='kami';
						if(cardNature=='ice') datasetNature='ice';
					}
					let bg=node.querySelector('div');
					if (bg) {
						Array.from(node.childNodes).filter(v=>v!=bg).forEach(v=>node.removeChild(v));
					}
					else bg=ui.create.div(node);
					node.classList.add('tempimage');
					let img=lib.card[cardName].image;
					if(img){
						if(img.startsWith('db:')){
							img=img.slice(3);
						}
						else if(!img.startsWith('ext:')){
							img=null;
						}
					}
					if(lib.card[cardName].fullskin){
						if(img){
							if(img.startsWith('ext:')){
								bg.setBackgroundImage(img.replace(/^ext:/,'extension/'));
							}
							else{
								bg.setBackgroundDB(img);
							}
						}
						else{
							if(lib.card[cardName].modeimage){
								bg.setBackgroundImage('image/mode/'+lib.card[cardName].modeimage+'/card/'+cardName+'.png');
							}
							else{
								if(cardName=='sha'&&cardNature=='stab') bg.setBackgroundImage('image/card/cisha.png');
								else bg.setBackgroundImage('image/card/'+cardName+'.png');
							}
						}
					}
					else if(lib.card[cardName].image=='background'){
						if(cardNature) bg.setBackground(cardName+'_'+cardNature,'card');
						else bg.setBackground(cardName,'card');
					}
					else if(lib.card[cardName].fullimage){
						if(img){
							if(img.startsWith('ext:')){
								bg.setBackgroundImage(img.replace(/^ext:/,'extension/'));
								bg.style.backgroundSize='cover';
							}
							else{
								bg.setBackgroundDB(img);
							}
						}
						else if(lib.card[cardName].image){
							if(lib.card[cardName].image.startsWith('character:')){
								bg.setBackground(lib.card[cardName].image.slice(10),'character');
							}
							else{
								bg.setBackground(lib.card[cardName].image);
							}
						}
						else{
							let cardPack=lib.cardPack['mode_'+get.mode()];
							if(Array.isArray(cardPack)&&cardPack.contains(cardName)){
								bg.setBackground('mode/'+get.mode()+'/card/'+cardName);
							}
							else{
								bg.setBackground('card/'+cardName);
							}
						}
					}
					else if(lib.card[cardName].image=='card'){
						if(cardNature) bg.setBackground(cardName+'_'+cardNature,'card');
						else bg.setBackground(cardName,'card');
					}
					else if(typeof lib.card[cardName].image=='string'&&!lib.card[cardName].fullskin){
						if(img){
							if(img.startsWith('ext:')){
								bg.setBackgroundImage(img.replace(/^ext:/,'extension/'));
								bg.style.backgroundSize='cover';
							}
							else{
								bg.setBackgroundDB(img);
							}
						}
						else{
							bg.setBackground(lib.card[cardName].image);
						}
					}
					else{
						console.warn('卡牌图片解析失败');
					}
					if(datasetNature.length>0){
						node.classList.add(datasetNature);
					}
					delete node.dataset.nature;
				}
				node.innerHTML+=`<span>${cardTempNameConfig=='default'?get.verticalStr(tempname):tempname}</span>`;
				node.tempname=tempname;
				return node;
			},
			connectRooms:function(list){
				ui.rooms=[];
				ui.roombase=ui.create.dialog();
				ui.roombase.classList.add('fullwidth');
				ui.roombase.classList.add('fullheight');
				ui.roombase.classList.add('fixed');
				ui.roombase.classList.add('scroll1');
				ui.roombase.classList.add('scroll2');
				ui.roombase.classList.add('noupdate');
				for(var i=0;i<list.length;i++){
					var player=ui.roombase.add('<div class="popup text pointerdiv" style="width:calc(100% - 10px);display:inline-block;white-space:nowrap">空房间</div>');
					player.roomindex=i;
					player.initRoom=lib.element.player.initRoom;
					player.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.connectroom);
					player.initRoom(list[i]);
					ui.rooms.push(player);
				}
			},
			rarity:function(button){
				var rarity=game.getRarity(button.link);
				if(rarity!='common'&&lib.config.show_rarity){
					var intro=button.node.intro;
					intro.classList.add('showintro');
					intro.style.fontFamily='yuanli';
					intro.style.fontSize='16px';
					intro.style.bottom='6px';
					intro.style.left='6px';
					switch(rarity){
						case 'rare':intro.dataset.nature='thunderm';break;
						case 'epic':intro.dataset.nature='metalm';break;
						case 'legend':intro.dataset.nature='orangem';break;
						case 'junk':intro.dataset.nature='woodm';break;
					}
					intro.innerHTML=get.translation(rarity);
				}
				/*if((button.link=='xushu'||button.link=='xin_xushu'||button.link=='jsrg_guanyu')&&button.node&&button.node.name&&button.node.group){
					if(button.classList.contains('newstyle')){
						button.node.name.dataset.nature='watermm';
						button.node.group.dataset.nature='water';
					}
					else button.node.group.style.backgroundColor=get.translation('weiColor');
				}*/
			},
			div:function(){
				var str,innerHTML,position,position2,style,divposition,listen;
				for(var i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='string'){
						if(typeof str=='string'){
							innerHTML=arguments[i];
						}
						else{
							str=arguments[i];
						}
					}
					else if(get.objtype(arguments[i])=='div'||
						get.objtype(arguments[i])=='table'||
						get.objtype(arguments[i])=='tr'||
						get.objtype(arguments[i])=='td'||
						get.objtype(arguments[i])=='body') position=arguments[i];
					else if(typeof arguments[i]=='number') position2=arguments[i];
					else if(get.itemtype(arguments[i])=='divposition') divposition=arguments[i];
					else if(typeof arguments[i]=='object') style=arguments[i];
					else if(typeof arguments[i]=='function') listen=arguments[i];
				}
				if(str==undefined) str='';
				var node=document.createElement('div');
				for(var i=0;i<str.length;i++){
					if(str[i]=='.'){
						if(node.className.length!=0){
							node.className+=' ';
						}
						while(str[i+1]!='.'&&str[i+1]!='#'&&i+1<str.length){
							node.className+=str[i+1];
							i++;
						}
					}
					else if(str[i]=='#'){
						while(str[i+1]!='.'&&str[i+1]!='#'&&i+1<str.length){
							node.id+=str[i+1];
							i++;
						}
					}
				}
				if(position){
					if(typeof position2=='number'&&position.childNodes.length>position2){
						position.insertBefore(node,position.childNodes[position2]);
					}
					else{
						position.appendChild(node);
					}
				}
				if(style) node.css(style);
				if(divposition) node.setPosition(divposition);
				if(innerHTML) node.innerHTML=innerHTML;
				if(listen) node.listen(listen);
				return node;
			},
			filediv:function(){
				var args=Array.from(arguments);
				var func=null;
				for(var i=0;i<args.length;i++){
					if(typeof args[i]=='function'){
						func=args[i];
						args.splice(i,1);
						break;
					}
				}
				var div=ui.create.div.apply(this,args);
				var input=ui.create.node('input.fileinput');
				input.type='file';
				input.onchange=function(e){
					func.call(this,this.files[0],e);
				};
				div.appendChild(input);
				div.inputNode=input;
				return div;
			},
			node:function(){
				var tagName,str,innerHTML,position,position2,style,divposition,listen;
				for(var i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='string'){
						if(typeof tagName=='string'){
							innerHTML=arguments[i];
						}
						else{
							tagName=arguments[i];
						}
					}
					else if(get.objtype(arguments[i])=='div'||
						get.objtype(arguments[i])=='table'||
						get.objtype(arguments[i])=='tr'||
						get.objtype(arguments[i])=='td'||
						get.objtype(arguments[i])=='body') position=arguments[i];
					else if(typeof arguments[i]=='number') position2=arguments[i];
					else if(get.itemtype(arguments[i])=='divposition') divposition=arguments[i];
					else if(typeof arguments[i]=='object') style=arguments[i];
					else if(typeof arguments[i]=='function') listen=arguments[i];
				}
				if(tagName==undefined){
					tagName='div';
				}
				else{
					var i1=tagName.indexOf('.');
					var i2=tagName.indexOf('#');
					if(i1!=-1||i2!=-1){
						if(i2!=-1&&i2<i1){
							i1=i2;
						}
						str=tagName.slice(i1);
						tagName=tagName.slice(0,i1);
					}
				}
				var node=document.createElement(tagName);
				if(str){
					for(var i=0;i<str.length;i++){
						if(str[i]=='.'){
							if(node.className.length!=0){
								node.className+=' ';
							}
							while(str[i+1]!='.'&&str[i+1]!='#'&&i+1<str.length){
								node.className+=str[i+1];
								i++;
							}
						}
						else if(str[i]=='#'){
							while(str[i+1]!='.'&&str[i+1]!='#'&&i+1<str.length){
								node.id+=str[i+1];
								i++;
							}
						}
					}
				}
				if(position){
					if(typeof position2=='number'&&position.childNodes.length>position2){
						position.insertBefore(node,position.childNodes[position2]);
					}
					else{
						position.appendChild(node);
					}
				}
				if(style) HTMLDivElement.prototype.css.call(node,style);
				if(divposition) HTMLDivElement.prototype.setPosition.call(node,divposition);
				if(innerHTML) node.innerHTML=innerHTML;
				if(listen) node.onclick=listen;
				return node;
			},
			iframe:function(src){
				var layer=document.createElement('div');
				layer.classList.add('poplayer');
				layer.style.zIndex='100';
				layer.listen(function(){
					this.remove();
				});
				layer.style.background='white';

				var webview=document.createElement('iframe');
				webview.src=src;
				webview.style.width='100%';
				webview.style.height='100%';
				webview.style.left='0px';
				webview.style.top='0px';
				webview.style.position='absolute';
				webview.style.border='none';
				layer.appendChild(webview);

				var backbutton=ui.create.div('.menubutton.round','返',layer,function(){
					layer.remove();
				});
				backbutton.style.bottom='10px';
				backbutton.style.right='10px';
				backbutton.style.background='rgba(0,0,0,0.4)';
				backbutton.style.color='white';
				backbutton.style.textShadow='rgba(0,0,0,0.5) 0px 0px 2px';
				backbutton.style.boxShadow='rgba(0, 0, 0, 0.3) 0 0 0 1px, rgba(0, 0, 0, 0.3) 0 3px 10px';
				backbutton.style.position='fixed';

				ui.window.appendChild(layer);
			},
			identitycircle:function(list,target){
				var container=ui.create.div('.identitycircle.menubg',target);
				var circle=ui.create.div(container);
				container.dataset.num=list.length;
				for(var i=0;i<list.length;i++){
					var sec1=ui.create.div(circle);
					sec1.dataset.color=list[i];
					var sec2=ui.create.div(circle);
					sec2.dataset.color=list[i];
					var deg1=360/list.length*i;
					var deg2=0;
					if(list.length==2){
						deg2=90;
					}
					else if(list.length==3){
						deg2=30;
					}
					sec1.style.transform='rotate('+deg1+'deg)';
					sec2.style.transform='rotate('+(deg1+deg2)+'deg)';
				}
			},
			chat:function(){
				var chat=ui.create.system('聊天',null,true);
				ui.chatButton=chat;
				lib.setPopped(chat,ui.click.chat,220);
			},
			exit:function(){
				if(!ui.exit){
					ui.exit=ui.create.control('退出房间',ui.click.exit);
				}
			},
			connecting:function(bool){
				if(bool){
					ui.window.classList.remove('connecting');
					if(ui.connecting){
						ui.connecting.delete();
						delete ui.connecting;
					}
				}
				else{
					ui.window.classList.add('connecting');
					ui.connecting=ui.create.div('.fullsize.connectlayer');
					document.body.appendChild(ui.connecting);
					ui.create.div('','正在重连...',ui.connecting);
					ui.connecting.splashtimeout=setTimeout(function(){
						if(ui.connecting){
							delete ui.connecting.splashtimeout;
						}
					},300);
					// setTimeout(function(){
					// 	if(ui.connecting){
					// 		ui.connecting.firstChild.show();
					// 	}
					// },1000);
				}
			},
			roomInfo:function(){
				var chat=ui.create.system(game.online?'房间信息':'房间设置',function(){
					if(!game.online||game.onlinezhu){
						ui.click.connectMenu();
					}
				},true);
				ui.roomInfo=chat;
				lib.setPopped(chat,function(){
					if(game.getRoomInfo){
						var uiintro=ui.create.dialog('hidden');
						game.getRoomInfo(uiintro);
						return uiintro;
					}
				},180);
			},
			templayer:function(time){
				if(typeof time!='number'||isNaN(time)||time==Infinity){
					time=500;
				}
				var templayer=ui.create.div('.popup-container',ui.window);
				setTimeout(function(){
					templayer.remove();
				},time);
			},
			selectlist:function(list,init,position,onchange){
				var select=document.createElement('select');
				for(var i=0;i<list.length;i++){
					var option=document.createElement('option');
					if(Array.isArray(list[i])){
						option.value=list[i][0];
						option.innerHTML=list[i][1];
					}
					else{
						option.value=list[i];
						option.innerHTML=list[i];
					}
					if(init==option.value){
						option.selected='selected';
					}
					select.appendChild(option);
				}
				if(position){
					position.appendChild(select);
				}
				if(onchange){
					select.onchange=onchange;
				}
				return select;
			},
			menu:function(connectMenu){
				var menuTimeout=null;
				if(!connectMenu&&!game.syncMenu){
					menuTimeout=setTimeout(lib.init.reset,1000);
				}
				var menu,menuContainer;
				var startButton;
				var popupContainer;
				var closeMenu=function(){
					if(popupContainer.noclose){
						popupContainer.noclose=false;
						return;
					}
					popupContainer.classList.add('hidden');
					if(popupContainer.onclose){
						popupContainer.onclose();
					}
				};
				popupContainer=ui.create.div('.popup-container.hidden',ui.window,closeMenu);

				var openMenu=function(node,e,onclose){
					popupContainer.innerHTML='';
					var left=Math.round(e.clientX/game.documentZoom);
					var zoom=get.is.phoneLayout?1.3:1;
					popupContainer.appendChild(node);
					// var rect=node.getBoundingClientRect();
					if(node.classList.contains('visual')){
						// var num=node.querySelectorAll('.menu.visual>div').length;
						// node.style.top=(e.y-node.offsetHeight/2+30)+'px';
						for(var i=0;i<node.childElementCount;i++){
							if(node.childNodes[i].update){
								node.childNodes[i].update();
							}
						}
						// if(node.offsetTop<10){
						// 	node.style.top='10px';
						// }
					}
					// else if(get.is.phoneLayout()&&rect.top*1.3+rect.height*1.3+20>ui.window.offsetHeight){
					// 	node.style.top=(ui.winheightdow.offsetHeight-20-rect.height*1.3)/1.3+'px';
					// }
					// if(e){
					var height=node.offsetHeight;
					var idealtop=e.clientY/game.documentZoom;
					if(idealtop<10){
						idealtop=10;
					}
					else if((idealtop+height)*zoom+10>ui.window.offsetHeight){
						idealtop=(ui.window.offsetHeight-10)/zoom-height;
					}
					node.style.top=idealtop+'px';
					node.style.left=left+'px';
					// }

					popupContainer.classList.remove('hidden');
					popupContainer.onclose=onclose;
				};
				var clickToggle=function(){
					if(this.classList.contains('disabled')) return;
					this.classList.toggle('on');
					var config=this._link.config;
					if(config.onclick){
						if(config.onclick.call(this,this.classList.contains('on'))===false){
							this.classList.toggle('on');
						}
					}
					if(config.update){
						config.update();
					}
				};
				var clickSwitcher=function(){
					if(this.classList.contains('disabled')) return;
					var node=this;
					this.classList.add('on');
					if(this._link.menu){
						var pos1=this.lastChild.getBoundingClientRect();
						var pos2=ui.window.getBoundingClientRect();
						if(this._link.menu.classList.contains('visual')){
							openMenu(this._link.menu,{
								clientX:pos1.left+pos1.width+5-pos2.left,
								clientY:pos1.top-pos2.top
							},function(){
								node.classList.remove('on');
							});
						}
						else if(this._link.menu.childElementCount>10){
							openMenu(this._link.menu,{
								clientX:pos1.left+pos1.width+5-pos2.left,
								clientY:Math.min((ui.window.offsetHeight-400)/2,pos1.top-pos2.top)
							},function(){
								node.classList.remove('on');
							});
							lib.setScroll(this._link.menu);
						}
						else{
							openMenu(this._link.menu,{
								clientX:pos1.left+pos1.width+5-pos2.left,
								clientY:pos1.top-pos2.top
							},function(){
								node.classList.remove('on');
							});
						}
					}
				};
				var clickContainer=function(){
					menuContainer.classList.add('hidden');
					if(connectMenu){
						if(_status.enteringroom){
							_status.enteringroom=false;
						}
						if(_status.creatingroom){
							_status.creatingroom=false;
						}
						ui.window.classList.remove('shortcutpaused');
					}
					else{
						game.resume2();
						if(game.onresume2){
							game.onresume2();
						}
						ui.arena.classList.remove('menupaused');
						ui.historybar.classList.remove('menupaused');
						ui.window.classList.remove('touchinfohidden');
						ui.config2.classList.remove('pressdown2');
					}
				};
				var clickMenuItem=function(){
					var node=this.parentNode._link;
					var config=node._link.config;
					node._link.current=this.link;
					var tmpName=node.lastChild.innerHTML;
					node.lastChild.innerHTML=config.item[this._link];
					if(config.onclick){
						if(config.onclick.call(node,this._link,this)===false){
							node.lastChild.innerHTML=tmpName;
						}
					}
					if(config.update){
						config.update();
					}
				};
				var createMenu=function(tabs,config){
					var createPage=function(position){
						var node=ui.create.div(position);
						lib.setScroll(ui.create.div('.left.pane',node));
						lib.setScroll(ui.create.div('.right.pane',node));
						return node;
					};
					var menu=ui.create.div('.main.menu.dialog.popped.static',config.position,function(e){
						e.stopPropagation();
					});
					if(connectMenu){
						menu.classList.add('center');
						menuContainer.classList.add('centermenu');
					}
					var menuTab=ui.create.div('.menu-tab',menu);
					var menuTabBar=ui.create.div('.menu-tab-bar',menu);
					menuTabBar.style.left=(config.bar||0)+'px';
					if(Math.round(2*game.documentZoom)<2){
						menuTabBar.style.height='3px';
					}
					var menuContent=ui.create.div('.menu-content',menu);
					var clickTab=function(){
						if(this.classList.contains('disabled')) return;
						var active=this.parentNode.querySelector('.active');
						if(active){
							active.classList.remove('active');
							active._link.remove();
						}
						this.classList.add('active');
						menuTabBar.style.transform='translateX('+(this.getBoundingClientRect().left-this.parentNode.firstChild.getBoundingClientRect().left)/game.documentZoom+'px)';
						menuContent.appendChild(this._link);
					};
					ui.click.menuTab=function(tab){
						for(var i=0;i<menuTab.childNodes.length;i++){
							if(menuTab.childNodes[i].innerHTML==tab){
								clickTab.call(menuTab.childNodes[i]);
								return;
							}
						}
					};
					var pages=[];
					for(var i=0;i<tabs.length;i++){
						var active=(i===(config.init||0));
						pages[i]=createPage(active?menuContent:null);
						ui.create.div(active?'.active':'',tabs[i],menuTab,clickTab)._link=pages[i];
					}
					return {
						menu:menu,
						pages:pages
					};
				};
				var createConfig=function(config,position){
					var node=ui.create.div('.config',config.name);
					node._link={config:config};
					if(!config.clear){
						if(config.name!='开启'){
							if(config.name=='屏蔽弱将'){
								config.intro='强度过低的武将(孙策除外)不会出现在选将框,也不会被AI选择'
							}
							else if(config.name=='屏蔽强将'){
								config.intro='强度过高的武将不会出现在选将框,也不会被AI选择'
							}
							else if(!config.intro){
								config.intro='设置'+config.name;
							}
							lib.setIntro(node,function(uiintro){
								if(lib.config.touchscreen) _status.dragged=true;
								uiintro.style.width='170px';
								var str=config.intro;
								if(typeof str=='function'){
									str=str();
								}
								uiintro._place_text=uiintro.add('<div class="text" style="display:inline">'+str+'</div>');
							});
						}
					}
					else{
						node.innerHTML='<span>'+config.name+'</span>';
						if(!config.nopointer){
							node.classList.add('pointerspan');
						}
					}
					if(config.item){
						if(typeof config.item=='function'){
							config.item=config.item();
						}
						if(Array.isArray(config.init)){

						}
						else{
							node.classList.add('switcher');
							node.listen(clickSwitcher);
							node._link.choosing=ui.create.div('',config.item[config.init],node);
							node._link.menu=ui.create.div('.menu');
							if(config.visualMenu){
								node._link.menu.classList.add('visual');
								var updateVisual=function(){
									config.visualMenu(this,this._link,config.item[this._link],config);
								};
								var createNode=function(i,before){
									var visualMenu=ui.create.div();
									if(config.visualBar){
										if(before){
											node._link.menu.insertBefore(visualMenu,before);
										}
										else{
											node._link.menu.insertBefore(visualMenu,node._link.menu.lastChild);
										}
									}
									else{
										node._link.menu.appendChild(visualMenu);
									}
									ui.create.div('.name',get.verticalStr(config.item[i]),visualMenu);
									visualMenu._link=i;
									if(config.visualMenu(visualMenu,i,config.item[i],config)!==false){
										visualMenu.listen(clickMenuItem);
									}
									visualMenu.update=updateVisual;
								};
								if(config.visualBar){
									var visualBar=ui.create.div(node._link.menu,function(){
										this.parentNode.parentNode.noclose=true;
									});
									node._link.menu.classList.add('withbar');
									config.visualBar(visualBar,config.item,createNode,node);
									visualBar.update=function(){
										config.visualBar(visualBar,config.item,createNode,node);
									}
								}
								for(var i in config.item){
									createNode(i);
								}
								lib.setScroll(node._link.menu);
								node._link.menu.updateBr=function(){
									var br=Array.from(this.querySelectorAll('.menu.visual>br'));
									while(br.length){
										br.shift().remove();
									}
									var split=[];
									for(var i=1;i<this.childElementCount;i++){
										if(i%3==0){
											split.push(this.childNodes[i]);
										}
									}
									for(var i=0;i<split.length;i++){
										this.insertBefore(ui.create.node('br'),split[i]);
									}
								}
								node._link.menu.updateBr();
							}
							else{
								for(var i in config.item){
									var textMenu=ui.create.div('',config.item[i],node._link.menu,clickMenuItem);
									textMenu._link=i;
									if(config.textMenu){
										config.textMenu(textMenu,i,config.item[i],config)
									}
									lib.setScroll(node._link.menu);
								}
							}
							node._link.menu._link=node;
							node._link.current=config.init;
						}
					}
					else if(config.range){

					}
					else if(config.clear){
						if(node.innerHTML.length>=15) node.style.height='auto';
						node.listen(clickToggle);
					}
					else if(config.input){
						node.classList.add('switcher');
						var input=ui.create.div(node);
						if(!config.fixed){
							input.contentEditable=true;
							input.style.webkitUserSelect='text';
						}
						input.style.minWidth='10px';
						input.style.maxWidth='60%';
						input.style.overflow='hidden';
						input.style.whiteSpace='nowrap';
						input.onkeydown=function(e){
							if(e.keyCode==13){
								e.preventDefault();
								e.stopPropagation();
								input.blur();
							}
						};
						if(config.name=='联机昵称'){
							input.innerHTML=config.init||'无名玩家';
							input.onblur=function(){
								input.innerHTML=input.innerHTML.replace(/<br>/g,'');
								if(!input.innerHTML||get.is.banWords(input.innerHTML)){
									input.innerHTML='无名玩家';
								}
								input.innerHTML=input.innerHTML.slice(0,12);
								game.saveConfig('connect_nickname',input.innerHTML);
								game.saveConfig('connect_nickname',input.innerHTML,'connect');
							}
						}
						else if(config.name=='联机大厅'){
							input.innerHTML=config.init||lib.hallURL;
							input.onblur=function(){
								if(!input.innerHTML){
									input.innerHTML=lib.hallURL;
								}
								input.innerHTML=input.innerHTML.replace(/<br>/g,'');
								game.saveConfig('hall_ip',input.innerHTML,'connect');
							}
						}
						else{
							input.innerHTML=config.init;
							input.onblur=config.onblur;
						}
					}
					else{
						node.classList.add('toggle');
						node.listen(clickToggle);
						ui.create.div(ui.create.div(node));
						if(config.init==true){
							node.classList.add('on');
						}
					}
					if(position){
						position.appendChild(node);
					}
					return node;
				};
				var updateActive,updateActiveCard;
				var menuUpdates=[];
				menuContainer=ui.create.div('.menu-container.hidden',ui.window,clickContainer);
				var menux;
				if(!connectMenu){
					ui.menuContainer=menuContainer;
					ui.click.configMenu=function(){
						ui.click.shortcut(false)
						if(menuContainer.classList.contains('hidden')){
							ui.config2.classList.add('pressdown2');
							ui.arena.classList.add('menupaused');
							ui.historybar.classList.add('menupaused');
							ui.window.classList.add('touchinfohidden');
							menuContainer.classList.remove('hidden');
							for(var i=0;i<menuUpdates.length;i++){
								menuUpdates[i]();
							}
						}
						else{
							clickContainer.call(menuContainer);
						}
					}
					menux=createMenu(['开始','选项','武将','卡牌','扩展','其它'],{
						position:menuContainer,bar:40
					});
				}
				else{
					ui.connectMenuContainer=menuContainer;
					ui.click.connectMenu=function(){
						if(menuContainer.classList.contains('hidden')){
							if(_status.waitingForPlayer){
								startButton.innerHTML='设';
								var start=menux.pages[0].firstChild;
								for(var i=0;i<start.childNodes.length;i++){
									if(start.childNodes[i].mode!=lib.configOL.mode){
										start.childNodes[i].classList.add('unselectable');
										start.childNodes[i].classList.remove('active');
										if(start.childNodes[i].link) start.childNodes[i].link.remove();
									}
									else{
										start.childNodes[i].classList.add('active');
										if(start.childNodes[i].link) start.nextSibling.appendChild(start.childNodes[i].link);
										else console.log(start.nextSibling, start.childNodes[i]);
									}
								}
							}
							ui.window.classList.add('shortcutpaused');
							menuContainer.classList.remove('hidden');
							for(var i=0;i<menuUpdates.length;i++){
								menuUpdates[i]();
							}
						}
						else{
							clickContainer.call(menuContainer);
						}
					}

					menux=createMenu(['模式','武将','卡牌'],{
						position:menuContainer,bar:123
					});
					menu=menux.menu;
				}
				var menuxpages=menux.pages.slice(0);

				var copyObj=get.copy;

				(function(){
					var start=menuxpages.shift();
					var rightPane=start.lastChild;

					startButton=ui.create.div('.menubutton.round.highlight','启',start,function(){
						if(this.animating||this.classList.contains('dim')){
							return;
						}
						var active=this.parentNode.querySelector('.active');
						if(active){
							if(connectMenu){
								if(_status.waitingForPlayer){
									var config={};
									for(var i in lib.mode[lib.configOL.mode].connect){
										if(i=='update') continue;
										config[i.slice(8)]=get.config(i,lib.configOL.mode);
									}
									config.zhinang_tricks=lib.config.connect_zhinang_tricks;
									if(game.online){
										if(game.onlinezhu){
											game.send('changeRoomConfig',config);
										}
									}
									else{
										game.broadcastAll(function(config){
											for(var i in config){
												lib.configOL[i]=config[i];
											}
										},config);
										if(lib.configOL.mode=='identity'&&lib.configOL.identity_mode=='zhong'&&game.connectPlayers){
											for(var i=0;i<game.connectPlayers.length;i++){
												game.connectPlayers[i].classList.remove('unselectable2');
											}
											lib.configOL.number=8;
											game.updateWaiting();
										}
										if(game.onlineroom){
											game.send('server','config',lib.configOL);
										}
										game.connectPlayers[0].chat('房间设置已更改');
									}
								}
								else if(_status.enteringroom||_status.creatingroom){
									lib.configOL.mode=active.mode;
									if(_status.enteringroomserver){
										game.saveConfig('connect_mode',lib.configOL.mode);

										var config={};
										for(var i in lib.mode[lib.configOL.mode].connect){
											if(i=='update') continue;
											config[i.slice(8)]=get.config(i,lib.configOL.mode);
										}
										config.zhinang_tricks=lib.config.connect_zhinang_tricks;

										config.characterPack=lib.connectCharacterPack.slice(0);
										config.cardPack=lib.connectCardPack.slice(0);
										for(var i=0;i<lib.config.connect_characters.length;i++){
											config.characterPack.remove(lib.config.connect_characters[i]);
										}
										for(var i=0;i<lib.config.connect_cards.length;i++){
											config.cardPack.remove(lib.config.connect_cards[i]);
										}
										config.banned=lib.config['connect_'+active.mode+'_banned'];
										config.bannedcards=lib.config['connect_'+active.mode+'_bannedcards'];
										game.send('server','create',game.onlineKey,get.connectNickname(),lib.config.connect_avatar,config,active.mode);
									}
									else{
										game.send('server','create',game.onlineKey,get.connectNickname(),lib.config.connect_avatar);
									}
								}
								else{
									localStorage.setItem(lib.configprefix+'directstart',true);
									game.saveConfig('directstartmode',active.mode);
									game.saveConfig('mode','connect');
									ui.exitroom=ui.create.system('退出房间',function(){
										game.saveConfig('directstartmode');
										game.reload();
									},true);
									game.switchMode(active.mode);
								}
								clickContainer.call(menuContainer);
							}
							else{
								game.saveConfig('mode',active.mode);
								localStorage.setItem(lib.configprefix+'directstart',true);
								game.reload();
							}
						}
					});

					var clickMode=function(){
						if(this.classList.contains('unselectable')) return;
						var active=this.parentNode.querySelector('.active');
						if(active===this){
							return;
						}
						active.classList.remove('active');
						active.link.remove();
						active=this;
						this.classList.add('active');
						if(this.link) rightPane.appendChild(this.link);
						else{
							this._initLink();
							rightPane.appendChild(this.link);
						}
						if(connectMenu){
							if(updateActive) updateActive();
							if(updateActiveCard) updateActiveCard();
						}
					};

					var createModeConfig=function(mode,position){
						var info=lib.mode[mode];
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large',info.name,position,clickMode);
						node.mode=mode;
						var connectDisplayMap={
							connect_player_number: null,
							connect_versus_mode: null,
						}
						var updateConnectDisplayMap=function(){
							if(_status.waitingForPlayer){
								if(connectDisplayMap.connect_player_number){
									connectDisplayMap.connect_player_number.style.display='none';
								}
								if(connectDisplayMap.connect_versus_mode){
									connectDisplayMap.connect_versus_mode.style.display='none';
								}
							}
						};
						if(connectMenu){
							menuUpdates.push(updateConnectDisplayMap);
							if(mode==lib.config.connect_mode){
								node.classList.add('active');
							}
						}
						else{
							if(mode==lib.config.mode){
								node.classList.add('active');
							}
						}
						node._initLink=function(){
							node.link=page;
							//“更多”下的内容
							var map={};
							var infoconfig=connectMenu?info.connect:info.config;
							if(infoconfig){
								var hiddenNodes=[];
								var config=lib.config.mode_config[mode]||{};
								if(connectMenu){
									infoconfig.connect_choose_timeout={
										name:'出牌时限',
										init:'30',
										item:{
											'10':'10秒',
											'15':'15秒',
											'30':'30秒',
											'60':'60秒',
											'90':'90秒',
										},
										connect:true,
										frequent:true
									};
									infoconfig.connect_observe={
										name:'允许旁观',
										init:true,
										connect:true
									};
									infoconfig.connect_observe_handcard={
										name:'允许观看手牌',
										init:false,
										connect:true
									};
								}
								for(var j in infoconfig){
									if(j==='update'){
										continue;
									}
									var cfg=copyObj(infoconfig[j]);
									cfg._name=j;
									cfg.mode=mode;
									if(!config.hasOwnProperty(j)){
										game.saveConfig(j,cfg.init,mode);
									}
									else{
										cfg.init=config[j];
									}
									if(!cfg.onclick){
										cfg.onclick=function(result){
											var cfg=this._link.config;
											game.saveConfig(cfg._name,result,mode);
											if(cfg.onsave){
												cfg.onsave.call(this,result);
											}
											if(!_status.connectMode||game.online){
												if(typeof cfg.restart=='function'){
													if(cfg.restart()){
														startButton.classList.add('glowing');
													}
												}
												else if(cfg.restart){
													startButton.classList.add('glowing');
												}
											}
										};
									}
									if(infoconfig.update){
										cfg.update=function(){
											infoconfig.update(config,map);
										};
									}
									var cfgnode=createConfig(cfg);
									map[j]=cfgnode;
									if(cfg.frequent){
										page.appendChild(cfgnode);
									}
									else{
										cfgnode.classList.add('auto-hide');
										hiddenNodes.push(cfgnode);
									}
								}
								if(!connectMenu){
									var move=ui.create.div('.auto-hide.config','<div style="margin-right:10px" class="pointerdiv">上移↑</div><div class="pointerdiv">下移↓</div>');
									move.firstChild.listen(function(){
										if(node.previousSibling){
											node.parentNode.insertBefore(node,node.previousSibling);
											var order=[];
											for(var i=0;i<node.parentNode.childNodes.length;i++){
												order.push(node.parentNode.childNodes[i].mode);
											}
											game.saveConfig('modeorder',order);
										}
									});
									move.lastChild.listen(function(){
										if(node.nextSibling){
											if(node.nextSibling.nextSibling){
												node.parentNode.insertBefore(node,node.nextSibling.nextSibling);
											}
											else{
												node.parentNode.insertBefore(node.nextSibling,node);
											}
											var order=[];
											for(var i=0;i<node.parentNode.childNodes.length;i++){
												order.push(node.parentNode.childNodes[i].mode);
											}
											game.saveConfig('modeorder',order);
										}
									});
									hiddenNodes.push(move);
								}
								var expanded=false;
								var hasexpand=true;
								if(hiddenNodes.length){
									if(lib.config.fold_mode){
										var clickmore=function(type){
											if(type==='expand'&&expanded) return;
											if(type==='unexpand'&&!expanded) return;
											if(expanded){
												this.classList.remove('on');
												this.parentNode.classList.remove('expanded');
											}
											else{
												this.classList.add('on');
												this.parentNode.classList.add('expanded');
											}
											expanded=!expanded;
										};
										var morenodes=ui.create.div('.config.more','更多 <div>&gt;</div>',page);
										morenodes.listen(clickmore);
										morenodes._onclick=clickmore;
										page.morenodes=morenodes;
									}
									else{
										page.classList.add('expanded');
										if(!connectMenu){
											page.classList.add('expanded2');
										}
									}
									for(var k=0;k<hiddenNodes.length;k++){
										page.appendChild(hiddenNodes[k]);
									}
								}
								else{
									hasexpand=false;
								}
								if(!connectMenu){
									var hidemode=ui.create.div('.config.pointerspan','<span>隐藏此模式</span>',page,function(){
										if(this.firstChild.innerHTML=='隐藏此模式'){
											this.firstChild.innerHTML='此模式将在重启后隐藏';
											lib.config.hiddenModePack.add(mode);
											if(!lib.config.prompt_hidepack){
												alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
												game.saveConfig('prompt_hidepack',true);
											}
										}
										else{
											this.firstChild.innerHTML='隐藏此模式';
											lib.config.hiddenModePack.remove(mode);
										}
										game.saveConfig('hiddenModePack',lib.config.hiddenModePack);
									});
									if(hasexpand){
										hidemode.classList.add('auto-hide');
									}
								}
								if(infoconfig.update){
									infoconfig.update(config,map);
									node.update=function(){
										infoconfig.update(config,map);
									}
								}
							}
							if(connectMenu){
								connectDisplayMap.connect_player_number=map.connect_player_number;
								connectDisplayMap.connect_versus_mode=map.connect_versus_mode;
								updateConnectDisplayMap();
							}
						};
						if(!get.config('menu_loadondemand')) node._initLink();
						return node;
					};
					var modeorder=lib.config.modeorder||[];
					for(var i in lib.mode){
						modeorder.add(i);
					}
					for(var i=0;i<modeorder.length;i++){
						if(connectMenu){
							if(!lib.mode[modeorder[i]].connect) continue;
							if(!lib.config['connect_'+modeorder[i]+'_banned']){
								lib.config['connect_'+modeorder[i]+'_banned']=[];
							}
							if(!lib.config['connect_'+modeorder[i]+'_bannedcards']){
								lib.config['connect_'+modeorder[i]+'_bannedcards']=[];
							}
						}
						if(lib.config.all.mode.contains(modeorder[i])){
							createModeConfig(modeorder[i],start.firstChild);
						}
					}
					var active=start.firstChild.querySelector('.active');
					if(!active){
						active=start.firstChild.firstChild;
						active.classList.add('active');
					}
					if(!active.link) active._initLink();
					rightPane.appendChild(active.link);
					if(lib.config.fold_mode){
						rightPane.addEventListener('mousewheel',function(e){
							var morenodes=this.firstChild.morenodes;
							if(morenodes){
								if(e.wheelDelta<0){
									morenodes._onclick.call(morenodes,'expand');
								}
								else if(this.scrollTop==0){
									morenodes._onclick.call(morenodes,'unexpand');
								}
							}
						},{passive:true});
					}
				}());

				(function(){
					if(connectMenu) return;
					var start=menuxpages.shift();
					var rightPane=start.lastChild;

					var clickMode=function(){
						var active=this.parentNode.querySelector('.active');
						if(active===this){
							return;
						}
						active.classList.remove('active');
						active.link.remove();
						active=this;
						active.classList.add('active');
						if(this.link) rightPane.appendChild(this.link);
						else{
							this._initLink();
							rightPane.appendChild(this.link);
						}
					};

					var clickAutoSkill=function(bool){
						var name=this._link.config._name;
						var list=lib.config.autoskilllist;
						if(bool){
							list.remove(name);
						}
						else{
							list.add(name);
						}
						game.saveConfig('autoskilllist',list);
					};
					var skilllistexpanded=game.expandSkills(lib.skilllist);
					for(var i in lib.skill){
						if(!skilllistexpanded.contains(i)) continue;
						if(lib.skill[i].frequent&&lib.translate[i]){
							lib.configMenu.skill.config[i]={
								name:lib.translate[i+'_noconf']||lib.translate[i],
								init:true,
								type:'autoskill',
								onclick:clickAutoSkill,
								intro:lib.translate[i+'_info']
							}
						}
					}
					var clickBanSkill=function(bool){
						var name=this._link.config._name;
						var list=lib.config.forbidlist;
						if(bool){
							list.remove(name);
						}
						else{
							list.add(name);
						}
						game.saveConfig('forbidlist',list);
					};
					var forbid=lib.config.forbid;
					if(!lib.config.forbidlist){
						game.saveConfig('forbidlist',[]);
					}
					for(var i=0;i<forbid.length;i++){
						var skip=false;
						var str='';
						var str2='';
						var str3='';
						for(var j=0;j<forbid[i].length;j++){
							if(!lib.skilllist.contains(forbid[i][j])){
								skip=true;
								break;
							}
							str+=get.translation(forbid[i][j])+'+';
							str2+=forbid[i][j]+'+';
							str3+=get.translation(forbid[i][j])+':'+lib.translate[forbid[i][j]+'_info'];
							if(j<forbid[i].length-1){
								str3+='<div class="placeholder slim" style="display:block;height:8px"></div>';
							}
						}
						if(skip) continue;
						str=str.slice(0,str.length-1);
						str2=str2.slice(0,str2.length-1);

						lib.configMenu.skill.config[str2]={
							name:str,
							init:true,
							type:'banskill',
							onclick:clickBanSkill,
							intro:str3
						}
					}

					var updateView=null;
					var updateAppearence=null;
					var createModeConfig=function(mode,position){
						var info=lib.configMenu[mode];
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large',info.name,position,clickMode);
						node.mode=mode;
						// node._initLink=function(){
							node.link=page;
							var map={};
							if(info.config){
								var hiddenNodes=[];
								var autoskillNodes=[];
								var banskillNodes=[];
								var custombanskillNodes=[];
								var banskill;

								if(mode=='skill'){
									var autoskillexpanded=false;
									var banskillexpanded=false;
									ui.create.div('.config.more','自动发动 <div>&gt;</div>',page,function(){
										if(autoskillexpanded){
											this.classList.remove('on');
											for(var k=0;k<autoskillNodes.length;k++){
												autoskillNodes[k].style.display='none';
											}
										}
										else{
											this.classList.add('on');
											for(var k=0;k<autoskillNodes.length;k++){
												autoskillNodes[k].style.display='';
											}
										}
										autoskillexpanded=!autoskillexpanded;
									});
									banskill=ui.create.div('.config.more','双将禁配 <div>&gt;</div>',page,function(){
										if(banskillexpanded){
											this.classList.remove('on');
											for(var k=0;k<banskillNodes.length;k++){
												banskillNodes[k].style.display='none';
											}
										}
										else{
											this.classList.add('on');
											for(var k=0;k<banskillNodes.length;k++){
												banskillNodes[k].style.display='';
											}
										}
										banskillexpanded=!banskillexpanded;
									});

									var banskilladd=ui.create.div('.config.indent','<span class="pointerdiv">添加...</span>',page,function(){
										this.nextSibling.classList.toggle('hidden');
									});
									banskilladd.style.display='none';
									banskillNodes.push(banskilladd);

									var banskilladdNode=ui.create.div('.config.indent.hidden.banskilladd',page);
									banskilladdNode.style.display='none';
									banskillNodes.push(banskilladdNode);

									var matchBanSkill=function(skills1,skills2){
										if(skills1.length!=skills2.length) return false;
										for(var i=0;i<skills1.length;i++){
											if(!skills2.contains(skills1[i])) return false;
										}
										return true;
									}
									var deleteCustomBanSkill=function(){
										for(var i=0;i<lib.config.customforbid.length;i++){
											if(matchBanSkill(lib.config.customforbid[i],this.parentNode.link)){
												lib.config.customforbid.splice(i--,1);
												break;
											}
										}
										game.saveConfig('customforbid',lib.config.customforbid);
										this.parentNode.remove();
									}
									var createCustomBanSkill=function(skills){
										var node=ui.create.div('.config.indent.toggle');
										node.style.display='none';
										node.link=skills;
										banskillNodes.push(node);
										custombanskillNodes.push(node);
										var str=get.translation(skills[0]);
										for(var i=1;i<skills.length;i++){
											str+='+'+get.translation(skills[i]);
										}
										node.innerHTML=str;
										var span=document.createElement('span');
										span.classList.add('cardpiledelete');
										span.innerHTML='删除';
										span.onclick=deleteCustomBanSkill;
										node.appendChild(span);
										page.insertBefore(node,banskilladdNode.nextSibling);
										return node;
									};
									for(var i=0;i<lib.config.customforbid.length;i++){
										createCustomBanSkill(lib.config.customforbid[i]);
									}
									(function(){
										var list=[];
										for(var i in lib.character){
											if(lib.character[i][3].length)
											list.push([i,lib.translate[i]]);
										}

										list.sort(function(a,b){
											a=a[0];b=b[0];
											var aa=a,bb=b;
											if(aa.includes('_')){
												aa=aa.slice(aa.indexOf('_')+1);
											}
											if(bb.includes('_')){
												bb=bb.slice(bb.indexOf('_')+1);
											}
											if(aa!=bb){
												return aa>bb?1:-1;
											}
											return a>b?1:-1;
										});

										var list2=[];
										var skills=lib.character[list[0][0]][3];
										for(var i=0;i<skills.length;i++){
											list2.push([skills[i],lib.translate[skills[i]]]);
										}

										var selectname=ui.create.selectlist(list,list[0],banskilladdNode);
										selectname.onchange=function(){
											var skills=lib.character[this.value][3];
											skillopt.innerHTML='';
											for(var i=0;i<skills.length;i++){
												var option=document.createElement('option');
												option.value=skills[i];
												option.innerHTML=lib.translate[skills[i]];
												skillopt.appendChild(option);
											}
										};
										selectname.style.maxWidth='85px';
										var skillopt=ui.create.selectlist(list2,list2[0],banskilladdNode);

										var span=document.createElement('span');
										span.innerHTML='+';
										banskilladdNode.appendChild(span);
										var br=document.createElement('br');
										banskilladdNode.appendChild(br);

										var selectname2=ui.create.selectlist(list,list[0],banskilladdNode);
										selectname2.onchange=function(){
											var skills=lib.character[this.value][3];
											skillopt2.innerHTML='';
											for(var i=0;i<skills.length;i++){
												var option=document.createElement('option');
												option.value=skills[i];
												option.innerHTML=lib.translate[skills[i]];
												skillopt2.appendChild(option);
											}
										};
										selectname2.style.maxWidth='85px';
										var skillopt2=ui.create.selectlist(list2,list2[0],banskilladdNode);
										var confirmbutton=document.createElement('button');
										confirmbutton.innerHTML='确定';
										banskilladdNode.appendChild(confirmbutton);

										confirmbutton.onclick=function(){
											var skills=[skillopt.value,skillopt2.value];
											if(skills[0]==skills[1]){
												skills.shift();
											}
											if(!lib.config.customforbid) return;
											for(var i=0;i<lib.config.customforbid.length;i++){
												if(matchBanSkill(lib.config.customforbid[i],skills)) return;
											}
											lib.config.customforbid.push(skills);
											game.saveConfig('customforbid',lib.config.customforbid);
											createCustomBanSkill(skills).style.display='';
										}
									}());
									page.style.paddingBottom='10px';
								}
								var config=lib.config;
								if(mode=='appearence'){
									updateAppearence=function(){
										info.config.update(config,map);
									};
								}
								else if(mode=='view'){
									updateView=function(){
										info.config.update(config,map);
									};
								}
								for(var j in info.config){
									if(j==='update'){
										continue;
									}
									var cfg=copyObj(info.config[j]);
									cfg._name=j;
									if(!config.hasOwnProperty(j)){
										if(cfg.type!='autoskill'&&cfg.type!='banskill'){
											game.saveConfig(j,cfg.init);
										}
									}
									else{
										cfg.init=config[j];
									}
									if(!cfg.onclick){
										cfg.onclick=function(result){
											var cfg=this._link.config;
											game.saveConfig(cfg._name,result);
											if(cfg.onsave){
												cfg.onsave.call(this,result);
											}
										};
									}
									if(info.config.update){
										if(mode=='appearence'||mode=='view'){
											cfg.update=function(){
												if(updateAppearence){
													updateAppearence();
												}
												if(updateView){
													updateView();
												}
											};
										}
										else{
											cfg.update=function(){
												info.config.update(config,map);
											};
										}
									}
									var cfgnode=createConfig(cfg);
									if(cfg.type=='autoskill'){
										autoskillNodes.push(cfgnode);
										// cfgnode.style.transition='all 0s';
										cfgnode.classList.add('indent');
										// cfgnode.hide();
										cfgnode.style.display='none';
									}
									else if(cfg.type=='banskill'){
										banskillNodes.push(cfgnode);
										// cfgnode.style.transition='all 0s';
										cfgnode.classList.add('indent');
										// cfgnode.hide();
										cfgnode.style.display='none';
									}
									if(j=='import_data_button'){
										ui.import_data_button=cfgnode;
										cfgnode.hide();
										cfgnode.querySelector('button').onclick=function(){
											var fileToLoad=this.previousSibling.files[0];
											if(fileToLoad){
												var fileReader = new FileReader();
												fileReader.onload = function(fileLoadedEvent)
												{
													var data = fileLoadedEvent.target.result;
													if(!data) return;
													try{
														data=JSON.parse(lib.init.decode(data));
														if(!data||typeof data!='object'){
															throw('err');
														}
														if(lib.db&&(!data.config||!data.data)){
															throw('err');
														}
													}
													catch(e){
														console.log(e);
														alert('导入失败');
														return;
													}
													alert('导入成功');
													if(!lib.db){
														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);
														}
														for(var i in data){
															localStorage.setItem(i,data[i]);
														}
													}
													else{
														for(var i in data.config){
															game.putDB('config',i,data.config[i]);
															lib.config[i]=data.config[i];
														}
														for(var i in data.data){
															game.putDB('data',i,data.data[i]);
														}
													}
													lib.init.background();
													game.reload();
												};
												fileReader.readAsText(fileToLoad, "UTF-8");
											}
										}
									}
									else if(j=='import_music'){
										cfgnode.querySelector('button').onclick=function(){
											if(_status.music_importing) return;
											_status.music_importing=true;
											var fileToLoad=this.previousSibling.files[0];
											if(fileToLoad){
												if(!lib.config.customBackgroundMusic) lib.config.customBackgroundMusic={};
												var name=fileToLoad.name;
												if(name.includes('.')){
													name=name.slice(0,name.indexOf('.'));
												}
												var link=(game.writeFile?'cdv_':'custom_')+name;
												if(lib.config.customBackgroundMusic[link]){
													if(!confirm('已经存在文件名称相同的背景音乐,是否仍然要继续导入?')){_status.music_importing=false;return};
													for(var i=1;i<1000;i++){
														if(!lib.config.customBackgroundMusic[link+'_'+i]){
															link=link+'_'+i;break;
														}
													}
												}
												var callback=function(){
													var nodexx=ui.background_music_setting;
													var nodeyy=nodexx._link.menu;
													var nodezz=nodexx._link.config;
													var musicname=link.slice(link.indexOf('_')+1);
													game.prompt('###请输入音乐的名称###'+musicname,true,function(str){
														if(str) musicname=str;
														lib.config.customBackgroundMusic[link]=musicname;
														lib.config.background_music=link;
														lib.config.all.background_music.add(link);
														game.saveConfig('background_music',link);
														game.saveConfig('customBackgroundMusic',lib.config.customBackgroundMusic);
														nodezz.item[link]=lib.config.customBackgroundMusic[link];
														var textMenu=ui.create.div('',lib.config.customBackgroundMusic[link],nodeyy,clickMenuItem,nodeyy.childElementCount-2);
														textMenu._link=link;
														nodezz.updatex.call(nodexx,[]);
														_status.music_importing=false;
														if(!_status._aozhan) game.playBackgroundMusic();
													});
												};
												if(game.writeFile){
													game.writeFile(fileToLoad,'audio/background',link+'.mp3',callback);
												}
												else{
													game.putDB('audio',link,fileToLoad,callback);
												}
											}
										}
									}
									else if(j=='extension_source'){
										ui.extension_source=cfgnode;
										cfgnode.updateInner=function(){
											this._link.choosing.innerHTML=lib.config.extension_source;
										}
									}
									map[j]=cfgnode;
									if(!cfg.unfrequent){
										if(cfg.type=='autoskill'){
											page.insertBefore(cfgnode,banskill);
										}
										else{
											page.appendChild(cfgnode);
										}
									}
									else{
										// cfgnode.classList.add('auto-hide');
										hiddenNodes.push(cfgnode);
									}
								}
								var expanded=false;
								if(hiddenNodes.length){
									// ui.create.div('.config.more','更多 <div>&gt;</div>',page,function(){
									//     if(expanded){
									//      			this.classList.remove('on');
									//      			this.parentNode.classList.remove('expanded');
									//     }
									//     else{
									//      			this.classList.add('on');
									//      			this.parentNode.classList.add('expanded');
									//     }
									//     expanded=!expanded;
									// });
									page.classList.add('morenodes');
									for(var k=0;k<hiddenNodes.length;k++){
										page.appendChild(hiddenNodes[k]);
									}
								}
								if(info.config.update){
									info.config.update(config,map);
								}
							}
						// };
						// if(!get.config('menu_loadondemand')) node._initLink();
						return node;
					};

					for(var i in lib.configMenu){
						if(i!='others') createModeConfig(i,start.firstChild);
					}
					(function(){
						if(!game.download&&!lib.device) return;
						var page=ui.create.div('#create-extension');
						var node=ui.create.div('.menubutton.large','文件',start.firstChild,clickMode);
						node.mode='create';
						node._initLink=function(){
							node.link=page;
							var pageboard=ui.create.div(page);

							var importextensionexpanded=false;
							var importExtension;
							var extensionnode=ui.create.div('.config.more','导入素材包 <div>&gt;</div>',pageboard,function(){
								if(importextensionexpanded){
									this.classList.remove('on');
									importExtension.style.display='none';
								}
								else{
									this.classList.add('on');
									importExtension.style.display='';
								}
								importextensionexpanded=!importextensionexpanded;
							});
							extensionnode.style.padding='13px 33px 4px';
							extensionnode.style.left='0px';
							importExtension=ui.create.div('.new_character.export.import',pageboard);
							importExtension.style.padding='0px 33px 10px';
							importExtension.style.display='none';
							importExtension.style.width='100%';
							importExtension.style.textAlign='left';
							ui.create.div('','<input type="file" accept="application/zip" style="width:153px"><button>确定</button>',importExtension);
							var promptnode=ui.create.div('','<div style="width:153px;font-size:small;margin-top:8px">',importExtension);
							promptnode.style.display='none';
							importExtension.firstChild.lastChild.onclick=function(){
								if(promptnode.style.display!='none') return;
								var fileToLoad=this.previousSibling.files[0];
								if(fileToLoad){
									promptnode.style.display='';
									promptnode.firstChild.innerHTML='正在解压...';
									var fileReader = new FileReader();
									fileReader.onload = function(fileLoadedEvent)
									{
										var data = fileLoadedEvent.target.result;
										var loadData=function(){
											var zip=new JSZip();
											zip.load(data);
											var images=[],audios=[],fonts=[],directories={},directoryList=[];
											Object.keys(zip.files).forEach(file=>{
												const parsedPath=lib.path.parse(file),directory=parsedPath.dir,fileExtension=parsedPath.ext.toLowerCase();
												if(directory.startsWith('audio')&&(fileExtension=='.mp3'||fileExtension=='.ogg')) audios.push(file);
												else if(directory.startsWith('font')&&fileExtension=='.woff2') fonts.push(file);
												else if(directory.startsWith('image')&&(fileExtension=='.jpg'||fileExtension=='.png')) images.push(file);
												else return;
												if(!directories[directory]){
													directories[directory]=[];
													directoryList.push(directory);
												}
												directories[directory].push(parsedPath.base);
											});
											if(audios.length||fonts.length||images.length){
												var str='';
												if(audios.length){
													str+=audios.length+'个音频文件';
												}
												if(fonts.length){
													if(str.length) str+='、'
													str+=fonts.length+'个字体文件';
												}
												if(images.length){
													if(str.length) str+='、'
													str+=images.length+'个图片文件';
												}
												var filelist=audios.concat(fonts).concat(images);
												if(filelist.length>200){
													str+=',导入时间可能较长';
												}
												var assetLoaded=function(){
													promptnode.firstChild.innerHTML='导入成功。<span class="hrefnode">重新启动</span><span class="closenode">×</span>';
													promptnode.firstChild.querySelectorAll('span')[0].onclick=game.reload;
													promptnode.firstChild.querySelectorAll('span')[1].onclick=function(){
														promptnode.style.display='none';
													}
												};
												if(confirm('本次将导入'+str+',是否继续?')){
													promptnode.firstChild.innerHTML='正在导入... <span class="hrefnode">详细信息</span>';
													promptnode.firstChild.querySelector('span.hrefnode').onclick=ui.click.consoleMenu;
													if(lib.node&&lib.node.fs){
														var writeFile=function(){
															if(filelist.length){
																var str=filelist.shift();
																game.print(str.slice(str.lastIndexOf('/')+1));
																lib.node.fs.writeFile(__dirname+'/'+str,zip.files[str].asNodeBuffer(),null,writeFile);
															}
															else{
																assetLoaded();
															}
														};
														game.ensureDirectory(directoryList,writeFile);

													}
													else{
														var getDirectory=function(){
															if(directoryList.length){
																var dir=directoryList.shift();
																var filelist=directories[dir];
																window.resolveLocalFileSystemURL(lib.assetURL+dir,function(entry){
																	var writeFile=function(){
																		if(filelist.length){
																			var filename=filelist.shift();
																			game.print(filename);
																			entry.getFile(filename,{create:true},function(fileEntry){
																				fileEntry.createWriter(function(fileWriter){
																					fileWriter.onwriteend=writeFile;
																					fileWriter.onerror = function(e) {
																						game.print('Write failed: ' + e.toString());
																					};
																					fileWriter.write(zip.files[dir+'/'+filename].asArrayBuffer());
																				});
																			});
																		}
																		else{
																			getDirectory();
																		}
																	};
																	writeFile();
																});
															}
															else{
																assetLoaded();
															}
														};
														game.ensureDirectory(directoryList,getDirectory);
													}
												}
												else{
													promptnode.style.display='none';
												}
											}
											else{
												alert('没有检测到素材');
											}
										}
										if(!window.JSZip){
											lib.init.js(lib.assetURL+'game','jszip',loadData);
										}
										else{
											loadData();
										}
									};
									fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
								}
							}

							var dashboard=ui.create.div(pageboard);
							var clickDash=function(){
								ui.create.templayer();
								pageboard.hide();
								this.link.show();
								if(this.link.init){
									this.link.init();
								}
							};
							var createDash=function(str1,str2,node){
								var dash=ui.create.div('.menubutton.large.dashboard');
								dashboard.appendChild(dash);
								page.appendChild(node);
								dash.link=node;
								node.link=dash;
								dash.listen(clickDash);
								lib.setScroll(node);
								ui.create.div('',str1,dash);
								ui.create.div('',str2,dash);
							};
							var createDash2=function(str1,str2,path,page){
								var dash=ui.create.div('.menubutton.large.dashboard.dashboard2');
								page.appendChild(dash);
								dash.listen(function(){
									page.path=path;
									enterDirectory(page,path);
								});
								ui.create.div('',str1,dash);
								ui.create.div('',str2,dash);
							};
							var removeFile=function(selected,page){
								if(lib.node&&lib.node.fs){
									var unlink=function(){
										if(selected.length){
											lib.node.fs.unlink(__dirname+'/'+selected.shift().path,unlink);
										}
										else{
											enterDirectory(page,page.currentpath);
										}
									}
									unlink();
								}
								else{
									window.resolveLocalFileSystemURL(lib.assetURL+page.currentpath,function(entry){
										var unlink=function(){
											if(selected.length){
												entry.getFile(selected.shift().filename,{create:false},function(fileEntry){
													fileEntry.remove(unlink);
												});
											}
											else{
												enterDirectory(page,page.currentpath);
											}
										}
										unlink();
									});
								}
							};
							var clickDirectory=function(){
								if(_status.dragged) return;
								var page=this.parentNode.parentNode.parentNode;
								if(page.deletebutton.classList.contains('active')){
									if(confirm('确认删除'+this.innerHTML+'文件夹?(此操作不可撤销)')){
										if(lib.node&&lib.node.fs){
											try{
												var removeDirectory=function(path,callback){
													lib.node.fs.readdir(__dirname+'/'+path,function(err,list){
														if(err){
															console.log(err);
															return;
														}
														var removeFile=function(){
															if(list.length){
																var filename=list.shift();
																var url=__dirname+'/'+path+'/'+filename;
																if(lib.node.fs.statSync(url).isDirectory()){
																	removeDirectory(path+'/'+filename,removeFile);
																}
																else{
																	lib.node.fs.unlink(url,removeFile);
																}
															}
															else{
																lib.node.fs.rmdir(__dirname+'/'+path,callback);
															}
														}
														removeFile();
													});
												};
												removeDirectory(this.path,function(){
													enterDirectory(page,page.currentpath);
												});
											}
											catch(e){
												console.log(e);
											}
										}
										else{
											window.resolveLocalFileSystemURL(lib.assetURL+this.path,function(entry){
												entry.removeRecursively(function(){
													enterDirectory(page,page.currentpath);
												});
											});
										}
									}
									return;
								}
								enterDirectory(page,this.path);
							};
							var clickFile=function(){
								if(_status.dragged) return;
								var page=this.parentNode.parentNode.parentNode;
								if(page.deletebutton.classList.contains('active')){
									if(confirm('确认删除'+this.innerHTML+'?(此操作不可撤销)')){
										removeFile([this],page);
									}
									return;
								}
								this.classList.toggle('thundertext');
								page.clicked=true;
								if(this.ext=='jpg'||this.ext=='png'){
									if(this.classList.contains('thundertext')){
										if(!this.previewnode){
											this.previewnode=document.createElement('img');
											this.previewnode.src=lib.assetURL+this.path;
											this.previewnode.width='60';
											this.previewnode.style.maxHeight='120px';
											this.parentNode.appendChild(this.previewnode);
										}
									}
									else{
										if(this.previewnode){
											this.previewnode.remove();
											delete this.previewnode;
										}
									}
								}
								else if(this.ext=='mp3'||this.ext=='ogg'){
									if(this.classList.contains('thundertext')){
										if(!this.previewnode){
											this.previewnode=game.playAudio(this.path.slice(6));
										}
									}
									else{
										if(this.previewnode){
											this.previewnode.remove();
											delete this.previewnode;
										}
									}
								}
							};
							var clickFileList=function(){
								if(!this.parentNode) return;
								if(this.parentNode.clicked){
									this.parentNode.clicked=false;
								}
								else{
									var selected=Array.from(this.querySelectorAll('span.thundertext'));
									for(var i=0;i<selected.length;i++){
										selected[i].classList.remove('thundertext');
										if(selected[i].previewnode){
											selected[i].previewnode.remove();
											delete selected[i].previewnode;
										}
									}
								}
							};
							var enterDirectory=function(page,path){
								page.innerHTML='';
								page.currentpath=path;
								var backbutton=ui.create.div('.menubutton.round','返',page,function(){
									page.clicked=false;
									clickFileList.call(filelist);
									if(page.path==path){
										page.reset();
									}
									else{
										if(path.indexOf('/')==-1){
											enterDirectory(page,'');
										}
										else{
											enterDirectory(page,path.slice(0,path.lastIndexOf('/')));
										}
									}
								});
								backbutton.style.zIndex=1;
								backbutton.style.right='10px';
								backbutton.style.bottom='15px';


								var refresh=function(){
									enterDirectory(page,path);
								};
								var addbutton=ui.create.div('.menubutton.round','添',page,function(){
									var pos1=this.getBoundingClientRect();
									var pos2=ui.window.getBoundingClientRect();
									openMenu(this.menu,{
										clientX:pos1.left+pos1.width+5-pos2.left,
										clientY:pos1.top-pos2.top
									});
								});
								addbutton.menu=ui.create.div('.menu');
								ui.create.div('','添加文件',addbutton.menu,function(){
									popupContainer.noclose=true;
								});
								var createDir=function(str){
									if(lib.node&&lib.node.fs){
										lib.node.fs.mkdir(__dirname+'/'+path+'/'+str,refresh);
									}
									else{
										window.resolveLocalFileSystemURL(lib.assetURL+path,function(entry){
											entry.getDirectory(str,{create:true},refresh);
										});
									}
								};
								ui.create.div('','添加目录',addbutton.menu,function(){
									ui.create.templayer();
									game.prompt('输入目录名称',function(str){
										if(str){
											createDir(str);
										}
									});
								});
								var input=document.createElement('input');
								input.className='fileinput';
								input.type='file';
								input.onchange=function(){
									var fileToLoad=input.files[0];
									game.print(fileToLoad.name);
									if(fileToLoad){
										var fileReader = new FileReader();
										fileReader.onload = function(e){
											game.writeFile(e.target.result,path,fileToLoad.name,refresh);
										};
										fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
									}
								};
								addbutton.menu.firstChild.appendChild(input);
								addbutton.style.zIndex=1;
								addbutton.style.right='10px';
								addbutton.style.bottom='80px';

								var deletebutton=ui.create.div('.menubutton.round','删',page,function(){
									if(!this.parentNode) return;
									if(!this.classList.contains('active')){
										var selected=Array.from(filelist.querySelectorAll('span.thundertext'));
										if(selected.length){
											if(confirm('一共要删除'+selected.length+'个文件,此操作不可撤销,是否确定?')){
												removeFile(selected,page);
											}
										}
										else{
											this.classList.add('active');
										}
									}
									else{
										this.classList.remove('active');
									}
								});
								deletebutton.style.zIndex=1;
								deletebutton.style.right='10px';
								deletebutton.style.bottom='145px';

								page.backbutton=backbutton;
								page.addbutton=addbutton;
								page.deletebutton=deletebutton;
								var filelist=ui.create.div(page);
								filelist.classList.add('file-container');
								filelist.listen(clickFileList);
								lib.setScroll(filelist);
								game.getFileList(path,function(folders,files){
									var sort=function(a,b){
										if(a>b) return 1;
										if(a<b) return -1;
										return 0;
									}
									folders.sort(sort);
									files.sort(sort);
									var parent=path;
									if(parent){
										parent+='/';
									}
									for(var i=0;i<folders.length;i++){
										if(!page.path&&folders[i]=='app') continue;
										var entry=ui.create.div('','<span>'+folders[i],filelist);
										entry.firstChild.addEventListener(lib.config.touchscreen?'touchend':'click',clickDirectory);
										entry.firstChild.path=parent+folders[i]
									}
									for(var i=0;i<files.length;i++){
										if(!page.path){
											if(files[i]=='app.html') continue;
											if(files[i]=='main.js') continue;
											if(files[i]=='package.json') continue;
										}
										var entry=ui.create.div('','<span>'+files[i],filelist);
										entry.firstChild.addEventListener(lib.config.touchscreen?'touchend':'click',clickFile);
										entry.firstChild.ext=files[i].slice(files[i].lastIndexOf('.')+1);
										entry.firstChild.path=parent+files[i];
										entry.firstChild.filename=files[i];
									}
								});
							};
							var dash1=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								page.reset=function(){
									page.innerHTML='';
									var backbutton=ui.create.div('.menubutton.round','返',page,function(){
										ui.create.templayer();
										page.hide();
										pageboard.show();
									});
									backbutton.style.zIndex=1;
									backbutton.style.right='10px';
									backbutton.style.bottom='15px';
									var placeholder=ui.create.div('.placeholder',page);
									placeholder.style.position='relative';
									placeholder.style.display='block';
									placeholder.style.width='100%';
									placeholder.style.height='14px';
									createDash2('将','武将图片','image/character',page);
									createDash2('肤','皮肤图片','image/skin',page);
									createDash2('卡','卡牌图片','image/card',page);
									createDash2('模','模式图片','image/mode',page);
									createDash2('始','开始图片','image/splash',page);
									createDash2('景','背景图片','image/background',page);
								};
								page.reset();
								return page;
							}());
							var dash2=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								page.reset=function(){
									page.innerHTML='';
									var backbutton=ui.create.div('.menubutton.round','返',page,function(){
										ui.create.templayer();
										page.hide();
										pageboard.show();
									});
									backbutton.style.zIndex=1;
									backbutton.style.right='10px';
									backbutton.style.bottom='15px';
									var placeholder=ui.create.div('.placeholder',page);
									placeholder.style.position='relative';
									placeholder.style.display='block';
									placeholder.style.width='100%';
									placeholder.style.height='14px';
									createDash2('技','技能配音','audio/skill',page);
									createDash2('卡','男性卡牌','audio/card/male',page);
									createDash2('牌','女性卡牌','audio/card/female',page);
									createDash2('亡','阵亡配音','audio/die',page);
									createDash2('效','游戏音效','audio/effect',page);
									createDash2('景','背景音乐','audio/background',page);
								};
								page.reset();
								return page;
							}());
							var dash3=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								page.path='font';
								page.reset=function(){
									ui.create.templayer();
									page.hide();
									pageboard.show();
								};
								page.init=function(){
									enterDirectory(page,'font');
								};
								return page;
							}());
							var dash4=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								page.path='';
								page.reset=function(){
									ui.create.templayer();
									page.hide();
									pageboard.show();
								};
								page.init=function(){
									enterDirectory(page,'');
								};
								return page;
							}());
							createDash('图','图片文件',dash1);
							createDash('音','音频文件',dash2);
							createDash('字','字体文件',dash3);
							createDash('全','全部文件',dash4);
						};
						if(!get.config('menu_loadondemand')) node._initLink();
					}());
					createModeConfig('others',start.firstChild);

					var active=start.firstChild.querySelector('.active');
					if(!active){
						active=start.firstChild.firstChild;
						active.classList.add('active');
					}
					if(!active.link) active._initLink();
					rightPane.appendChild(active.link);
				}());

				(function(){
					var start=menuxpages.shift();
					var rightPane=start.lastChild;

					var clickMode=function(){
						var active=this.parentNode.querySelector('.active');
						if(active){
							if(active===this){
								return;
							}
							active.classList.remove('active');
							active.link.remove();
						}
						this.classList.add('active');
						updateActive(this);
						if(this.link) rightPane.appendChild(this.link);
						else{
							this._initLink();
							rightPane.appendChild(this.link);
						}
					};
					updateActive=function(node){
						if(!node){
							node=start.firstChild.querySelector('.active');
							if(!node){
								return;
							}
						}
						if (!node.link) {
							node._initLink();
						}
						for(var i=0;i<node.link.childElementCount;i++){
							if(node.link.childNodes[i].updateBanned){
								node.link.childNodes[i].updateBanned();
							}
						}
					};
					var updateNodes=function(){
						for(var i=0;i<start.firstChild.childNodes.length;i++){
							var node=start.firstChild.childNodes[i];
							if(node.mode){
								if(node.mode.startsWith('mode_')) continue;
								if(node.mode=='custom') continue;
								if(connectMenu){
									if(!lib.config.connect_characters.contains(node.mode)){
										node.classList.remove('off');
										if(node.link) node.link.firstChild.classList.add('on');
									}
									else{
										node.classList.add('off');
										if(node.link) node.link.firstChild.classList.remove('on');
									}
								}
								else{
									if(lib.config.characters.contains(node.mode)){
										node.classList.remove('off');
										if(node.link) node.link.firstChild.classList.add('on');
									}
									else{
										node.classList.add('off');
										if(node.link) node.link.firstChild.classList.remove('on');
									}
								}
							}
						}
					}
					var togglePack=function(bool){
						var name=this._link.config._name;
						if(connectMenu){
							if(!bool){
								lib.config.connect_characters.add(name);
							}
							else{
								lib.config.connect_characters.remove(name);
							}
							game.saveConfig('connect_characters',lib.config.connect_characters);
						}
						else{
							if(bool){
								lib.config.characters.add(name);
							}
							else{
								lib.config.characters.remove(name);
							}
							game.saveConfig('characters',lib.config.characters);
						}
						updateNodes();
					};

					var createModeConfig=function(mode,position,position2){
						var _info=lib.characterPack[mode];
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large',lib.translate[mode+'_character_config'],position,clickMode);
						if(node.innerHTML.length>=5){
							node.classList.add('smallfont');
						}
						if(position2){
							position.insertBefore(node,position2);
						}
						node.mode=mode;
						node._initLink=function(){
							node.link=page;
							page.node=node;
							var list=[];
							var boolAI=true;
							var alterableSkills=[];
							var alterableCharacters=[];
							var charactersToAlter=[];
							for(var i in _info){
								if(_info[i][4]&&_info[i][4].contains('unseen')) continue;
								if(connectMenu&&lib.connectBanned.contains(i)) continue;
								list.push(i);
								if(boolAI&&!lib.config.forbidai_user.contains(i)) boolAI=false;
								for(var j=0;j<_info[i][3].length;j++){
									if(!lib.skill[_info[i][3][j]]){
										continue;
									}
									if(lib.skill[_info[i][3][j]].alter){
										alterableSkills.add(_info[i][3][j]);
										alterableCharacters.add(i);
										if(lib.config.vintageSkills.contains(_info[i][3][j])){
											charactersToAlter.add(i);
										}
									}
								}
							}
							alterableCharacters.sort();
							list.sort(lib.sort.character);
							var list2=list.slice(0);
							var cfgnode=createConfig({
								name:'开启',
								_name:mode,
								init:lib.config.characters.contains(mode),
								onclick:togglePack
							});
							var cfgnodeAI=createConfig({
								name:'仅点将可用',
								_name:mode,
								init:boolAI,
								intro:'将该武将包内的武将全部设置为仅点将可用',
								onclick:function(bool){
									if(bool){
										for(var i=0;i<list.length;i++){
											lib.config.forbidai_user.add(list[i]);
										}
									}
									else{
										for(var i=0;i<list.length;i++){
											lib.config.forbidai_user.remove(list[i]);
										}
									}
									game.saveConfig('forbidai_user',lib.config.forbidai_user);
								},
							});
							if(!mode.startsWith('mode_')){
								cfgnodeAI.style.marginTop='0px';
								page.appendChild(cfgnode);
								page.appendChild(cfgnodeAI);
								if(alterableCharacters.length){
									var cfgnode2=createConfig({
										name:'新版替换',
										_name:mode,
										init:charactersToAlter.length==0,
										intro:'以下武将将被修改:'+get.translation(alterableCharacters),
										onclick:function(bool){
											if(bool){
												for(var i=0;i<alterableSkills.length;i++){
													lib.config.vintageSkills.remove(alterableSkills[i]);
													lib.translate[alterableSkills[i]+'_info']=lib.translate[alterableSkills[i]+'_info_alter'];
												}
											}
											else{
												for(var i=0;i<alterableSkills.length;i++){
													lib.config.vintageSkills.add(alterableSkills[i]);
													lib.translate[alterableSkills[i]+'_info']=lib.translate[alterableSkills[i]+'_info_origin'];
												}
											}
											game.saveConfig('vintageSkills',lib.config.vintageSkills);
										}
									});
									cfgnode2.style.marginTop='0px';
									page.appendChild(cfgnode2);
								}
							}
							else if(mode.startsWith('mode_extension')){
								page.appendChild(cfgnodeAI);
							}
							else{
								page.style.paddingTop='8px';
							}
							var banCharacter=function(e){
								if(_status.clicked){
									_status.clicked=false;
									return;
								}
								if(mode.startsWith('mode_')&&!mode.startsWith('mode_extension_')&&
									mode!='mode_favourite'&&mode!='mode_banned'){
									if(!connectMenu&&lib.config.show_charactercard){
										ui.click.charactercard(this.link,this,mode=='mode_guozhan'?'guozhan':true);
									}
									return;
								}
								ui.click.touchpop();
								this._banning=connectMenu?'online':'offline';
								if(!connectMenu&&lib.config.show_charactercard){
									ui.click.charactercard(this.link,this);
								}
								else{
									ui.click.intro.call(this,e);
								}
								_status.clicked=false;
								delete this._banning;
							};
							var updateBanned=function(){
								var _list;
								if(connectMenu){
									var mode=menux.pages[0].firstChild.querySelector('.active');
									if(mode&&mode.mode){
										_list=lib.config['connect_'+mode.mode+'_banned'];
									}
								}
								else{
									_list=lib.config[get.mode()+'_banned'];
								}
								if(_list&&_list.contains(this.link)){
									this.classList.add('banned');
								}
								else{
									this.classList.remove('banned');
								}
							};
							if(lib.characterSort[mode]){
								var listb=[];
								if(!connectMenu){
									listb=lib.config[get.mode()+'_banned']||[];
								}
								else{
								var modex=menux.pages[0].firstChild.querySelector('.active');
									if(modex&&modex.mode){
										listb=lib.config['connect_'+modex.mode+'_banned'];
									}
								}
								for(var pak in lib.characterSort[mode]){
									var info=lib.characterSort[mode][pak];
									var listx=[];
									var boolx=false;
									for(var ii=0;ii<list2.length;ii++){
										if(info.contains(list2[ii])){
											listx.add(list2[ii]);
											if(!listb.contains(list2[ii])) boolx=true;
											list2.splice(ii--,1);
										}
									}
									if(listx.length){
										var cfgnodeY={
											name:lib.translate[pak],
											_name:pak,
											init:boolx,
											onclick:function(bool){
												var banned=[];
												if(connectMenu){
													var modex=menux.pages[0].firstChild.querySelector('.active');
													if(modex&&modex.mode){
														banned=lib.config['connect_'+modex.mode+'_banned'];
													}
												}
												else if(_status.connectMode) return;
												else banned=lib.config[get.mode()+'_banned']||[];
												var listx=lib.characterSort[mode][this._link.config._name];
												if(bool){
													for(var i=0;i<listx.length;i++){
														banned.remove(listx[i]);
													}
												}
												else{
													for(var i=0;i<listx.length;i++){
														banned.add(listx[i]);
													}
												}
												game.saveConfig(connectMenu?('connect_'+modex.mode+'_banned'):(get.mode()+'_banned'),banned);
												updateActive();
											},
										};
										if(mode.startsWith('mode_')&&!mode.startsWith('mode_extension_')&&!mode.startsWith('mode_guozhan')){
											cfgnodeY.clear=true;
											delete cfgnodeY.onclick;
										}
										var cfgnodeX=createConfig(cfgnodeY);
										page.appendChild(cfgnodeX);
										var buttons=ui.create.buttons(listx,'character',page);
										for(var i=0;i<buttons.length;i++){
											buttons[i].classList.add('noclick');
											buttons[i].listen(banCharacter);
											ui.create.rarity(buttons[i]);
											buttons[i].node.hp.style.transition='all 0s';
											buttons[i].node.hp._innerHTML=buttons[i].node.hp.innerHTML;
											if(mode!='mode_banned'){
												buttons[i].updateBanned=updateBanned;
											}
										}
									}
								}
								if(list2.length){
									var cfgnodeX=createConfig({
										name:'其他',
										_name:'others',
										clear:true,
									});
									page.appendChild(cfgnodeX);
									var buttons=ui.create.buttons(list2,'character',page);
									for(var i=0;i<buttons.length;i++){
										buttons[i].classList.add('noclick');
										buttons[i].listen(banCharacter);
										ui.create.rarity(buttons[i]);
										buttons[i].node.hp.style.transition='all 0s';
										buttons[i].node.hp._innerHTML=buttons[i].node.hp.innerHTML;
										if(mode!='mode_banned'){
											buttons[i].updateBanned=updateBanned;
										}
									}
								}
							}
							else{
								var buttons=ui.create.buttons(list,'character',page);
								for(var i=0;i<buttons.length;i++){
									buttons[i].classList.add('noclick');
									ui.create.rarity(buttons[i]);
									buttons[i].listen(banCharacter);
									buttons[i].node.hp.style.transition='all 0s';
									buttons[i].node.hp._innerHTML=buttons[i].node.hp.innerHTML;
									if(mode!='mode_banned'){
										buttons[i].updateBanned=updateBanned;
									}
								}
							}
							page.classList.add('menu-buttons');
							page.classList.add('leftbutton');
							if(!connectMenu){
								if(lib.config.all.sgscharacters.contains(mode)){
									ui.create.div('.config.pointerspan','<span style="opacity:0.5">该武将包不可被隐藏</span>',page);
								}
								else if(!mode.startsWith('mode_')){
									ui.create.div('.config.pointerspan','<span>隐藏武将包</span>',page,function(){
										if(this.firstChild.innerHTML=='隐藏武将包'){
											if(confirm('真的要隐藏“'+get.translation(mode+'_character_config')+'”武将包吗?\n建议使用“关闭”而不是“隐藏”功能,否则将会影响其他相关武将包的正常运行!')){
												this.firstChild.innerHTML='武将包将在重启后隐藏';
												lib.config.hiddenCharacterPack.add(mode);
												if(!lib.config.prompt_hidepack){
													alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
													game.saveConfig('prompt_hidepack',true);
												}
											}
										}
										else{
											this.firstChild.innerHTML='隐藏武将包';
											lib.config.hiddenCharacterPack.remove(mode);
										}
										game.saveConfig('hiddenCharacterPack',lib.config.hiddenCharacterPack);
									});
								}
							}
						};
						if(!get.config('menu_loadondemand')) node._initLink();
						return node;
					};
					if(lib.config.show_favourite_menu&&!connectMenu&&Array.isArray(lib.config.favouriteCharacter)){
						lib.characterPack.mode_favourite={};
						for(var i=0;i<lib.config.favouriteCharacter.length;i++){
							var favname=lib.config.favouriteCharacter[i];
							if(lib.character[favname]){
								lib.characterPack.mode_favourite[favname]=lib.character[favname];
							}
						}
						var favouriteCharacterNode=createModeConfig('mode_favourite',start.firstChild);
						if(!favouriteCharacterNode.link) favouriteCharacterNode._initLink();
						ui.favouriteCharacter=favouriteCharacterNode.link;
						if(get.is.empty(lib.characterPack.mode_favourite)){
							ui.favouriteCharacter.node.style.display='none';
						}
						delete lib.characterPack.mode_favourite;
					}
					if(!connectMenu&&lib.config.show_ban_menu){
						lib.characterPack.mode_banned={};
						for(var i=0;i<lib.config.all.mode.length;i++){
							var banned=lib.config[lib.config.all.mode[i]+'_banned'];
							if(banned){
								for(var j=0;j<banned.length;j++){
									if(lib.character[banned[j]]){
										lib.characterPack.mode_banned[banned[j]]=lib.character[banned[j]];
									}
								}
							}
						}
						var bannednode=createModeConfig('mode_banned',start.firstChild);
						if(get.is.empty(lib.characterPack.mode_banned)){
							bannednode.style.display='none';
						}
						delete lib.characterPack.mode_banned;
					}
					var characterlist=connectMenu?lib.connectCharacterPack:lib.config.all.characters;
					for(var i=0;i<characterlist.length;i++){
						createModeConfig(characterlist[i],start.firstChild);
					}
					if(!connectMenu) Object.keys(lib.characterPack).forEach(key=>{
						if(key.startsWith('mode_')) createModeConfig(key,start.firstChild);
					});
					var active=start.firstChild.querySelector('.active');
					if(!active){
						active=start.firstChild.firstChild;
						if(active.style.display=='none'){
							active=active.nextSibling;
							if(active.style.display=='none'){
								active=active.nextSibling;
							}
						}
						active.classList.add('active');
						updateActive(active);
					}
					if(!active.link) active._initLink();
					rightPane.appendChild(active.link);

					if(!connectMenu){
						var node1=ui.create.div('.lefttext','全部开启',start.firstChild,function(){
							game.saveConfig('characters',lib.config.all.characters);
							updateNodes();
						});
						var node2=ui.create.div('.lefttext','恢复默认',start.firstChild,function(){
							game.saveConfig('characters',lib.config.defaultcharacters);
							updateNodes();
						});
						node1.style.marginTop='12px';
						node2.style.marginTop='7px';
					}

					updateNodes();
				}());

				(function(){
					var start=menuxpages.shift();
					var rightPane=start.lastChild;
					var pileCreated=false;
					var recreatePile=function(){
						lib.config.customcardpile['当前牌堆']=[lib.config.bannedpile,lib.config.addedpile];
						game.saveConfig('customcardpile',lib.config.customcardpile);
						game.saveConfig('cardpilename','当前牌堆',true);
						pileCreated=false;
					};

					var clickMode=function(){
						var active=this.parentNode.querySelector('.active');
						if(active===this){
							return;
						}
						active.classList.remove('active');
						active.link.remove();
						active=this;
						this.classList.add('active');
						updateActiveCard(this);
						if(this.mode=='cardpile'){
							this.create();
						}
						if(this.link) rightPane.appendChild(this.link);
						else{
							this._initLink();
							rightPane.appendChild(this.link);
						}
					};
					updateActiveCard=function(node){
						if(!node){
							node=start.firstChild.querySelector('.active');
							if(!node){
								return;
							}
						}
						if(!node.link) node._initLink();
						for(var i=0;i<node.link.childElementCount;i++){
							if(node.link.childNodes[i].updateBanned){
								node.link.childNodes[i].updateBanned();
							}
						}
					};
					var updateNodes=function(){
						for(var i=0;i<start.firstChild.childNodes.length;i++){
							var node=start.firstChild.childNodes[i];
							if(node.mode){
								if(node.mode.startsWith('mode_')) continue;
								if(node.mode=='custom') continue;
								if(node.mode=='cardpile') continue;
								if(connectMenu){
									if(!lib.config.connect_cards.contains(node.mode)){
										node.classList.remove('off');
										if(node.link) node.link.firstChild.classList.add('on');
									}
									else{
										node.classList.add('off');
										if(node.link) node.link.firstChild.classList.remove('on');
									}
								}
								else{
									if(lib.config.cards.contains(node.mode)){
										node.classList.remove('off');
										if(node.link) node.link.firstChild.classList.add('on');
									}
									else{
										node.classList.add('off');
										if(node.link) node.link.firstChild.classList.remove('on');
									}
								}
							}
						}
					}
					var togglePack=function(bool){
						var name=this._link.config._name;
						if(connectMenu){
							if(!bool){
								lib.config.connect_cards.add(name);
							}
							else{
								lib.config.connect_cards.remove(name);
							}
							game.saveConfig('connect_cards',lib.config.connect_cards);
						}
						else{
							if(bool){
								lib.config.cards.add(name);
							}
							else{
								lib.config.cards.remove(name);
							}
							game.saveConfig('cards',lib.config.cards);
						}
						updateNodes();
					};
					var toggleCardPile=function(bool){
						var name=this._link.config._name;
						var number=this._link.config._number;
						if(!lib.config.bannedpile[name]){
							lib.config.bannedpile[name]=[];
						}
						if(bool){
							lib.config.bannedpile[name].remove(number);
						}
						else{
							lib.config.bannedpile[name].add(number);
						}
						recreatePile();
					}

					var createModeConfig=function(mode,position){
						var info=lib.cardPack[mode];
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large',lib.translate[mode+'_card_config'],position,clickMode);
						if(node.innerHTML.length>=5){
							node.classList.add('smallfont');
						}
						node.mode=mode;
						node._initLink=function(){
							node.link=page;
							var list=[];
							for(var i=0;i<info.length;i++){
								if(!lib.card[info[i]]||(lib.card[info[i]].derivation&&mode!='mode_derivation')) continue;
								list.push([get.translation(get.type(info[i],'trick')),'',info[i]]);
							}
							var sortCard=function(card){
								var type=lib.card[card[2]].type;
								var subtype=lib.card[card[2]].subtype;
								if(lib.cardType[subtype]){
									return lib.cardType[subtype];
								}
								if(lib.cardType[type]){
									return lib.cardType[type];
								}
								switch(type){
									case 'basic':return 0;
									case 'chess':return 1.5;
									case 'trick':return 2;
									case 'delay':return 3;
									case 'equip':{
										switch(lib.card[card[2]].subtype){
											case 'equip1':return 4.1;
											case 'equip2':return 4.2;
											case 'equip3':return 4.3;
											case 'equip4':return 4.4;
											case 'equip5':return 4.5;
											default:return 4;
										}
									}
									case 'zhenfa':return 5;
									default:return 6;
								}
							}
							list.sort(function(a,b){
								var sort1=sortCard(a);
								var sort2=sortCard(b);
								if(sort1==sort2){
									return (b[2]<a[2])?1:-1;
								}
								else if(sort1>sort2){
									return 1;
								}
								else{
									return -1;
								}
							});
							var cfgnode=createConfig({
								name:'开启',
								_name:mode,
								init:lib.config.cards.contains(mode),
								onclick:togglePack
							});
							if(!mode.startsWith('mode_')){
								page.appendChild(cfgnode);
							}
							else{
								page.style.paddingTop='8px';
							}
							var banCard=function(e){
								if(_status.clicked){
									_status.clicked=false;
									return;
								}
								if(mode.startsWith('mode_')&&!mode.startsWith('mode_extension_')&&mode!='mode_banned'){
									return;
								}
								ui.click.touchpop();
								this._banning=connectMenu?'online':'offline';
								ui.click.intro.call(this,e);
								_status.clicked=false;
								delete this._banning;
							};
							var updateBanned=function(){
								var list;
								if(connectMenu){
									var mode=menux.pages[0].firstChild.querySelector('.active');
									if(mode&&mode.mode){
										list=lib.config['connect_'+mode.mode+'_bannedcards'];
									}
								}
								else{
									list=lib.config[get.mode()+'_bannedcards'];
								}
								if(list&&list.contains(this.link[2])){
									this.classList.add('banned');
								}
								else{
									this.classList.remove('banned');
								}
							};
							var buttons=ui.create.buttons(list,'vcard',page);
							for(var i=0;i<buttons.length;i++){
								buttons[i].classList.add('noclick');
								buttons[i].listen(banCard);
								if(mode!='mode_banned'){
									buttons[i].updateBanned=updateBanned;
								}
							}
							page.classList.add('menu-buttons');
							page.classList.add('leftbutton');
							if(!connectMenu&&!lib.config.all.sgscards.contains(mode)&&!mode.startsWith('mode_')){
								ui.create.div('.config.pointerspan','<span>隐藏卡牌包</span>',page,function(){
									if(this.firstChild.innerHTML=='隐藏卡牌包'){
										this.firstChild.innerHTML='卡牌包将在重启后隐藏';
										lib.config.hiddenCardPack.add(mode);
										if(!lib.config.prompt_hidepack){
											alert('隐藏的扩展包可通过选项-其它-重置隐藏内容恢复');
											game.saveConfig('prompt_hidepack',true);
										}
									}
									else{
										this.firstChild.innerHTML='隐藏卡牌包';
										lib.config.hiddenCardPack.remove(mode);
									}
									game.saveConfig('hiddenCardPack',lib.config.hiddenCardPack);
								});
							}
							if(!mode.startsWith('mode_')&&lib.cardPile[mode]){
								var cardpileNodes=[];
								var cardpileexpanded=false;
								if(!lib.config.bannedpile[mode]){
									lib.config.bannedpile[mode]=[];
								}
								if(!lib.config.addedpile[mode]){
									lib.config.addedpile[mode]=[];
								}
								ui.create.div('.config.more.pile','编辑牌堆 <div>&gt;</div>',page,function(){
									if(cardpileexpanded){
										this.classList.remove('on');
										for(var k=0;k<cardpileNodes.length;k++){
											cardpileNodes[k].style.display='none';
										}
									}
									else{
										this.classList.add('on');
										for(var k=0;k<cardpileNodes.length;k++){
											cardpileNodes[k].style.display='';
										}
									}
									cardpileexpanded=!cardpileexpanded;
								});
								var cfgnode=ui.create.div(page,'.config.pointerspan.cardpilecfg.toggle');
								var cfgaddcard=ui.create.node('button','','添加卡牌',cfgnode,function(){
									this.parentNode.nextSibling.classList.toggle('hidden');
								});
								var cfgbancard=ui.create.node('button','','全部关闭',cfgnode,function(){
									for(var i=0;i<cardpileNodes.length;i++){
										if(cardpileNodes[i].type=='defaultcards'&&cardpileNodes[i].classList.contains('on')){
											clickToggle.call(cardpileNodes[i]);
										}
									}
								});
								var cfgenablecard=ui.create.node('button','','全部开启',cfgnode,function(){
									for(var i=0;i<cardpileNodes.length;i++){
										if(cardpileNodes[i].type=='defaultcards'&&!cardpileNodes[i].classList.contains('on')){
											clickToggle.call(cardpileNodes[i]);
										}
									}
								});
								cfgbancard.style.marginLeft='5px';
								cfgenablecard.style.marginLeft='5px';
								cardpileNodes.push(cfgnode);
								cfgnode.style.display='none';
								cfgnode.classList.add('cardpilecfg');
								cfgnode.classList.add('toggle');
								cfgnode.style.marginTop='5px';
								page.appendChild(cfgnode);

								var cardpileadd=ui.create.div('.config.toggle.hidden.cardpilecfg.cardpilecfgadd',page);
								var pileaddlist=[];
								for(var i=0;i<lib.config.cards.length;i++){
									if(!lib.cardPack[lib.config.cards[i]]) continue;
									for(var j=0;j<lib.cardPack[lib.config.cards[i]].length;j++){
										var cname=lib.cardPack[lib.config.cards[i]][j];
										pileaddlist.push([cname,get.translation(cname)]);
										if(cname=='sha'){
											pileaddlist.push(['huosha','火杀']);
											pileaddlist.push(['leisha','雷杀']);
											pileaddlist.push(['icesha','冰杀']);
											pileaddlist.push(['cisha','刺杀']);
										}
									}
								}
								var cardpileaddname=ui.create.selectlist(pileaddlist,null,cardpileadd);
								cardpileaddname.style.width='75px';
								cardpileaddname.style.marginRight='2px';
								cardpileaddname.style.marginLeft='-1px';
								var cardpileaddsuit=ui.create.selectlist([
									['heart','红桃'],
									['diamond','方片'],
									['club','梅花'],
									['spade','黑桃'],
								],null,cardpileadd);
								cardpileaddsuit.style.width='53px';
								cardpileaddsuit.style.marginRight='2px';
								var cardpileaddnumber=ui.create.selectlist([
									1,2,3,4,5,6,7,8,9,10,11,12,13
								],null,cardpileadd);
								cardpileaddnumber.style.width='43px';
								cardpileaddnumber.style.marginRight='2px';
								var button=document.createElement('button');
								button.innerHTML='确定';
								button.style.width='40px';
								var deletecard=function(){
									this.parentNode.remove();
									var info=this.parentNode._info;
									var list=lib.config.addedpile[mode];
									for(var i=0;i<list.length;i++){
										if(list[i][0]==info[0]&&list[i][1]==info[1]&&list[i][2]==info[2]){
											list.splice(i,1);break;
										}
									}
									recreatePile();
								};
								button.onclick=function(){
									var card=[
										cardpileaddsuit.value,
										cardpileaddnumber.value,
										cardpileaddname.value,
									];
									lib.config.addedpile[mode].push(card);
									recreatePile();
									var cfgnode=ui.create.div('.config.toggle.cardpilecfg');
									cfgnode._info=card;
									cfgnode.innerHTML=get.translation(card[2])+' '+get.translation(card[0])+get.strNumber(card[1]);
									var cfgnodedelete=document.createElement('span');
									cfgnodedelete.classList.add('cardpiledelete');
									cfgnodedelete.innerHTML='删除';
									cfgnodedelete.onclick=deletecard;
									cfgnode.appendChild(cfgnodedelete);
									page.insertBefore(cfgnode,cardpileadd.nextSibling);
								};
								cardpileadd.appendChild(button);
								cardpileadd.style.whiteSpace='nowrap';
								cardpileNodes.push(cardpileadd);

								for(var i=0;i<lib.config.addedpile[mode].length;i++){
									var card=lib.config.addedpile[mode][i];
									var cfgnode=ui.create.div('.config.toggle.cardpilecfg');
									cfgnode._info=card;
									cfgnode.innerHTML=get.translation(card[2])+' '+get.translation(card[0])+card[1];
									var cfgnodedelete=document.createElement('span');
									cfgnodedelete.classList.add('cardpiledelete');
									cfgnodedelete.innerHTML='删除';
									cfgnodedelete.onclick=deletecard;
									cfgnode.appendChild(cfgnodedelete);
									cfgnode.style.display='none';
									cardpileNodes.push(cfgnode);
									page.appendChild(cfgnode);
								}

								for(var i=0;i<lib.cardPile[mode].length;i++){
									var card=lib.cardPile[mode][i];
									var cfgnode=createConfig({
										name:((card[2]=='sha'&&card[3])?(get.translation(card[3])):'')+get.translation(card[2])+' '+get.translation(card[0])+get.strNumber(card[1]),
										_number:i,
										_name:mode,
										init:!lib.config.bannedpile[mode].contains(i),
										onclick:toggleCardPile
									});
									cfgnode.type='defaultcards';
									cardpileNodes.push(cfgnode);
									cfgnode.style.display='none';
									cfgnode.classList.add('cardpilecfg');
									page.appendChild(cfgnode);
								}
								ui.create.div('.menuplaceholder',page);
							}
						};
						if(!get.config('menu_loadondemand')) node._initLink();
						return node;
					};
					if(!connectMenu&&lib.config.show_ban_menu){
						lib.cardPack.mode_banned=[];
						for(var i=0;i<lib.config.all.mode.length;i++){
							var banned=lib.config[lib.config.all.mode[i]+'_bannedcards'];
							if(banned){
								for(var j=0;j<banned.length;j++){
									lib.cardPack.mode_banned.add(banned[j]);
								}
							}
						}
						var bannednode=createModeConfig('mode_banned',start.firstChild);
						if(lib.cardPack.mode_banned.length==0){
							bannednode.style.display='none';
						}
						delete lib.cardPack.mode_banned;
					}
					for(var i=0;i<lib.config.all.cards.length;i++){
						if(connectMenu&&!lib.connectCardPack.contains(lib.config.all.cards[i])) continue;
						createModeConfig(lib.config.all.cards[i],start.firstChild);
					}
					if(!connectMenu) Object.keys(lib.cardPack).forEach(key=>{
						if(key.startsWith('mode_')) createModeConfig(key,start.firstChild);
					});
					var active=start.firstChild.querySelector('.active');
					if(!active){
						active=start.firstChild.firstChild;
						if(active.style.display=='none'){
							active=active.nextSibling;
						}
						active.classList.add('active');
						updateActiveCard(active);
					}
					if(!active.link) active._initLink();
					rightPane.appendChild(active.link);

					(function(){
						if(connectMenu) return;
						var page=ui.create.div('.menu-buttons');
						var node=ui.create.div('.menubutton.large','牌堆',clickMode);
						start.firstChild.insertBefore(node,start.firstChild.querySelector('.lefttext'));
						node.link=page;
						node.mode='cardpile';
						node.create=function(){
							if(pileCreated) return;
							pileCreated=true;
							page.innerHTML='';

							var pileList=null;
							var createList=function(){
								if(pileList){
									pileList.remove();
								}
								var list=['默认牌堆'];
								if(lib.config.customcardpile['当前牌堆']){
									list.push('当前牌堆');
								}
								for(var i in lib.config.customcardpile){
									list.add(i);
								}
								var currentpile=get.config('cardpilename');
								if(!currentpile){
									if(list.contains('当前牌堆')){
										currentpile='当前牌堆';
									}
									else{
										currentpile='默认牌堆';
									}
								}
								pileList=ui.create.selectlist(list,currentpile,pileChoose,function(e){
									game.saveConfig('cardpilename',this.value,true);
									restart.style.display='';
								});
								pileList.style.float='right';
							}
							var pileChoose=ui.create.div('.config.toggle.cardpilecfg.nomarginleft','选择牌堆',page);
							createList();

							var pileDel=function(){
								delete lib.config.customcardpile[this.parentNode.link];
								this.parentNode.remove();
								game.saveConfig('customcardpile',lib.config.customcardpile);
								for(var i in lib.config.mode_config){
									if(i=='global') continue;
									if(lib.config.mode_config[i].cardpilename==this.parentNode.link){
										game.saveConfig('cardpilename',null,i);
									}
								}
								createList();
							};

							var restart=ui.create.div('.config.more','重新启动',game.reload,page);
							restart.style.display='none';
							var createPileNode=function(name){
								var node=ui.create.div('.config.toggle.cardpilecfg.nomarginleft',name);
								node.link=name;
								var del=document.createElement('span');
								del.innerHTML='删除';
								del.classList.add('cardpiledelete');
								del.onclick=pileDel;
								node.appendChild(del);
								if(name=='当前牌堆'){
									page.insertBefore(node,pileChoose.nextSibling);
								}
								else{
									page.insertBefore(node,restart);
								}
							};
							for(var i in lib.config.customcardpile){
								createPileNode(i);
							}
							var exportCardPile;
							ui.create.div('.config.more','保存当前牌堆 <div>&gt;</div>',page,function(){
								this.classList.toggle('on');
								if(this.classList.contains('on')){
									exportCardPile.classList.remove('hidden');
								}
								else{
									exportCardPile.classList.add('hidden');
								}
							});
							exportCardPile=ui.create.div('.config.cardpileadd.indent',page);
							exportCardPile.classList.add('hidden');
							ui.create.div('','名称:<input type="text"><button>确定</button>',exportCardPile);
							var input=exportCardPile.firstChild.lastChild.previousSibling;
							input.value='自定义牌堆';
							input.style.marginRight='3px';
							input.style.width='120px';
							exportCardPile.firstChild.lastChild.onclick=function(){
								var name=input.value;
								var ok=true;
								if(lib.config.customcardpile[name]||name=='默认牌堆'||name=='当前牌堆'){
									for(var i=1;i<=1000;i++){
										if(!lib.config.customcardpile[name+'('+i+')']){
											name=name+'('+i+')';
											break;
										}
									}
								}
								lib.config.customcardpile[name]=[lib.config.bannedpile,lib.config.addedpile];
								delete lib.config.customcardpile['当前牌堆'];
								for(var i in lib.mode){
									if(lib.config.mode_config[i]&&
										(lib.config.mode_config[i].cardpilename=='当前牌堆'||!lib.config.mode_config[i].cardpilename)){
										game.saveConfig('cardpilename',name,i);
									}
								}
								for(var i=0;i<page.childElementCount;i++){
									if(page.childNodes[i].link=='当前牌堆'){
										page.childNodes[i].remove();
										break;
									}
								}
								game.saveConfig('customcardpile',lib.config.customcardpile);
								createPileNode(name);
								createList();
							};
						}
					}());

					if(!connectMenu){
						var node1=ui.create.div('.lefttext','全部开启',start.firstChild,function(){
							game.saveConfig('cards',lib.config.all.cards);
							updateNodes();
						});
						var node2=ui.create.div('.lefttext','恢复默认',start.firstChild,function(){
							game.saveConfig('cards',lib.config.defaultcards);
							updateNodes();
						});
						node1.style.marginTop='12px';
						node2.style.marginTop='7px';
					}

					updateNodes();
				}());

				(function(){
					if(connectMenu) return;
					var start=menuxpages.shift();
					var rightPane=start.lastChild;

					var clickMode=function(){
						if(this.mode=='get'){
							this.update();
						}
						var active=this.parentNode.querySelector('.active');
						if(active===this){
							return;
						}
						active.classList.remove('active');
						active.link.remove();
						active=this;
						this.classList.add('active');
						if(this.link) rightPane.appendChild(this.link);
						else{
							this._initLink();
							rightPane.appendChild(this.link);
						}
						updateNodes();
					};
					ui.click.extensionTab=function(name){
						ui.click.menuTab('扩展');
						for(var i=0;i<start.firstChild.childElementCount;i++){
							if(start.firstChild.childNodes[i].innerHTML==name){
								clickMode.call(start.firstChild.childNodes[i]);
								break;
							}
						}
					}
					var updateNodes=function(){
						for(var i=0;i<start.firstChild.childNodes.length;i++){
							var node=start.firstChild.childNodes[i];
							if(node.mode=='get') continue;
							if(node.mode=='create') continue;
							if(node.mode&&node.mode.startsWith('extension_')){
								if(lib.config[node.mode+'_enable']){
									node.classList.remove('off');
									if(node.link) node.link.firstChild.classList.add('on');
								}
								else{
									node.classList.add('off');
									if(node.link) node.link.firstChild.classList.remove('on');
								}
							}
							else{
								if(lib.config.plays.contains(node.mode)){
									node.classList.remove('off');
									if(node.link) node.link.firstChild.classList.add('on');
								}
								else{
									node.classList.add('off');
									if(node.link) node.link.firstChild.classList.remove('on');
								}
							}
						}
					}
					var togglePack=function(bool){
						var name=this._link.config._name;
						if(name.startsWith('extension_')){
							if(bool){
								game.saveConfig(name,true);
							}
							else{
								game.saveConfig(name,false);
							}
						}
						else{
							name=name.slice(0,name.indexOf('_enable_playpackconfig'));
							if(bool){
								lib.config.plays.add(name);
							}
							else{
								lib.config.plays.remove(name);
							}
							game.saveConfig('plays',lib.config.plays);
						}
						if(this.onswitch){
							this.onswitch(bool);
						}
						updateNodes();
					};

					var createModeConfig=function(mode,position){
						var page=ui.create.div('');
						page.style.paddingBottom='10px';
						var node;
						if(mode.startsWith('extension_')){
							node=ui.create.div('.menubutton.large',mode.slice(10),position,clickMode);
						}
						else{
							node=ui.create.div('.menubutton.large',lib.translate[mode+'_play_config'],position,clickMode);
						}
						if(node.innerHTML.length>=5){
							node.classList.add('smallfont');
						}
						node.mode=mode;
						// node._initLink=function(){
							node.link=page;
							for(var i in lib.extensionMenu[mode]){
								if(i=='game') continue;
								var cfg=copyObj(lib.extensionMenu[mode][i]);
								var j;
								if(mode.startsWith('extension_')){
									j=mode+'_'+i;
								}
								else{
									j=mode+'_'+i+'_playpackconfig';
								}
								cfg._name=j;
								if(!lib.config.hasOwnProperty(j)){
									game.saveConfig(j,cfg.init);
								}
								else{
									cfg.init=lib.config[j];
								}

								if(i=='enable'){
									cfg.onclick=togglePack;
								}
								else if(!lib.extensionMenu[mode][i].onclick){
									cfg.onclick=function(result){
										var cfg=this._link.config;
										game.saveConfig(cfg._name,result);
									};
								}
								var cfgnode=createConfig(cfg);
								if(cfg.onswitch){
									cfgnode.onswitch=cfg.onswitch;
								}
								page.appendChild(cfgnode);
							}
						// };
						// if(!get.config('menu_loadondemand')) node._initLink();
						return node;
					};
					for(var i in lib.extensionMenu){
						if(lib.config.all.stockextension.contains(i)&&!lib.config.all.plays.contains(i)) continue;
						if(lib.config.hiddenPlayPack.contains(i)) continue;
						createModeConfig(i,start.firstChild);
					}
					(function(){
						if(!lib.device&&!lib.db) return;
						if(lib.config.show_extensionmaker==false) return;
						var page=ui.create.div('#create-extension');
						var node=ui.create.div('.menubutton.large','制作扩展',start.firstChild,clickMode);
						node.mode='create';
						game.editExtension=function(name){
							node._initLink();
							game.editExtension(name);
						};
						node._initLink=function(){
							node.link=page;
							var pageboard=ui.create.div(page);
							var inputExtLine=ui.create.div(pageboard);
							inputExtLine.style.transition='all 0s';
							inputExtLine.style.padding='10px';
							inputExtLine.style.height='22px';
							inputExtLine.style.lineHeight='22px';
							inputExtLine.style.whiteSpace='nowrap';
							inputExtLine.style.overflow='visible';
							var inputExtSpan=document.createElement('span');
							inputExtSpan.innerHTML='扩展名:';
							inputExtLine.appendChild(inputExtSpan);
							var inputExtName=document.createElement('input');
							inputExtName.type='text';
							inputExtName.value='无名扩展';
							inputExtName.style.width='80px';
							inputExtName.style.textAlign='center';
							inputExtLine.appendChild(inputExtName);

							var buttonConfirmOnclick=function(){
								buttonConfirm.style.display='none';
								inputExtSpan.style.display='none';
								inputExtName.style.display='none';
								authorExtLine.style.display='none';
								introExtLine.style.display='none';
								forumExtLine.style.display='none';
								diskExtLine.style.display='none';
								versionExtLine.style.display='none';
								okExtLine.style.display='none';
								inputExtLine.style.padding='10px';
								buttonRename.style.display='';
								buttonSave.style.display='';
								buttonReset.style.display='';
								buttonExport.style.display='';
								inputExtSpan.innerHTML='扩展名称:';
								inputExtName.style.width='100px';
								inputExtName.style.textAlign='';

								dashboard.style.display='';
							};
							var createExtLine=function(str,str2){
								var infoExtLine=ui.create.div(pageboard);
								infoExtLine.style.display='none';
								infoExtLine.style.padding='0 10px 10px 10px';
								infoExtLine.style.height='22px';
								infoExtLine.style.lineHeight='22px';
								infoExtLine.style.whiteSpace='nowrap';
								infoExtLine.style.overflow='visible';
								if(typeof str=='boolean'){
									var inputConfirm=document.createElement('button');
									inputConfirm.innerHTML='确定';
									inputConfirm.onclick=buttonConfirmOnclick;
									infoExtLine.appendChild(inputConfirm);
									return infoExtLine;
								}
								var infoExtSpan=document.createElement('span');
								infoExtSpan.innerHTML=str+':';
								infoExtLine.appendChild(infoExtSpan);
								var infoExtName=document.createElement('input');
								infoExtName.type='text';
								infoExtName.style.width='100px';
								infoExtName.value=str2||'';
								infoExtLine.appendChild(infoExtName);
								return infoExtLine;
							};
							var authorExtLine=createExtLine('扩展作者',get.connectNickname());
							var introExtLine=createExtLine('扩展描述');
							var versionExtLine=createExtLine('扩展版本','1.0');
							var diskExtLine=createExtLine('网盘地址');
							var forumExtLine=createExtLine('讨论地址');
							var okExtLine=createExtLine(true);

							game.editExtension=function(name){
								page.currentExtension=name||'无名扩展';
								inputExtName.value=page.currentExtension;
								if(name&&lib.extensionPack[name]){
									authorExtLine.querySelector('input').value=lib.extensionPack[name].author||'';
									introExtLine.querySelector('input').value=lib.extensionPack[name].intro||'';
									diskExtLine.querySelector('input').value=lib.extensionPack[name].diskURL||'';
									forumExtLine.querySelector('input').value=lib.extensionPack[name].forumURL||'';
									versionExtLine.querySelector('input').value=lib.extensionPack[name].version||'';
								}
								else{
									authorExtLine.querySelector('input').value=get.connectNickname()||'';
									introExtLine.querySelector('input').value='';
									diskExtLine.querySelector('input').value='';
									forumExtLine.querySelector('input').value='';
									versionExtLine.querySelector('input').value='1.0';
								}
								if(name){
									inputExtName.disabled=true;
									buttonConfirm.style.display='none';
									inputExtSpan.style.display='none';
									inputExtName.style.display='none';
									buttonRename.style.display='';
									buttonSave.style.display='';
									buttonReset.style.display='';
									buttonExport.style.display='';
								}
								else{
									inputExtName.disabled=false;
									buttonConfirm.style.display='';
									inputExtSpan.innerHTML='扩展名:';
									inputExtName.style.width='80px';
									inputExtName.style.textAlign='center';
									inputExtSpan.style.display='';
									inputExtName.style.display='';
									buttonRename.style.display='none';
									buttonSave.style.display='none';
									buttonReset.style.display='none';
									buttonExport.style.display='none';
								}

								dashboard.style.display='';

								exportExtLine.style.display='none';
								shareExtLine.style.display='none';
								authorExtLine.style.display='none';
								introExtLine.style.display='none';
								forumExtLine.style.display='none';
								diskExtLine.style.display='none';
								versionExtLine.style.display='none';
								okExtLine.style.display='none';
								inputExtLine.style.padding='10px';
								dash1.reset(name);
								dash2.reset(name);
								dash3.reset(name);
								dash4.reset(name);
								dash1.link.classList.remove('active');
								dash2.link.classList.remove('active');
								dash3.link.classList.remove('active');
								dash4.link.classList.remove('active');
								var active=node.parentNode.querySelector('.active');
								if(active===node){
									return;
								}
								active.classList.remove('active');
								active.link.remove();
								node.classList.add('active');
								rightPane.appendChild(node.link);
							}
							var processExtension=function(exportext){
								if(page.currentExtension){
									if(page.currentExtension!=inputExtName.value&&!exportext){
										game.removeExtension(page.currentExtension);
									}
								}
								inputExtName.disabled=true;
								setTimeout(function(){
									var ext={};
									var config=null,help=null;
									for(var i in dash4.content){
										try{
											if(i=='content'||i=='precontent'){
												eval('ext[i]='+dash4.content[i]);
												if(typeof ext[i]!='function'){
													throw('err');
												}
												else{
													ext[i]=ext[i].toString();
												}
											}
											else{
												eval(dash4.content[i]);
												eval('ext[i]='+i);
												if(ext[i]==null||typeof ext[i]!='object'){
													throw('err');
												}
												else{
													ext[i]=JSON.stringify(ext[i]);
												}
											}
										}
										catch(e){
											console.log(e);
											delete ext[i];
										}
									}
									page.currentExtension=inputExtName.value||'无名扩展';
									var str='{name:"'+page.currentExtension+'"';
									for(var i in ext){
										str+=','+i+':'+ext[i];
									}
									dash2.content.pack.list=[];
									for(var i=0;i<dash2.pile.childNodes.length;i++){
										dash2.content.pack.list.push(dash2.pile.childNodes[i].link);
									}
									str+=',package:'+get.stringify({
										//替换die audio,加上扩展名
										character:(pack=>{
											var character=pack.character;
											for (var key in character){
												var info=character[key];
												if(Array.isArray(info[4])){
													var tag=info[4].find(tag=>/^die:.+$/.test(tag));
													if(tag){
														info[4].remove(tag);
														if(typeof game.readFile=='function'){
															info[4].push('die:ext:'+page.currentExtension+'/audio/die/'+tag.slice(tag.lastIndexOf('/')+1));
														}else{
															info[4].push('die:db:extension-'+page.currentExtension+':audio/die/'+tag.slice(tag.lastIndexOf('/')+1));
														}
													}
												}
											}
											return pack;
										})(dash1.content.pack),
										card:dash2.content.pack,
										skill:dash3.content.pack,
										intro:introExtLine.querySelector('input').value||'',
										author:authorExtLine.querySelector('input').value||'',
										diskURL:diskExtLine.querySelector('input').value||'',
										forumURL:forumExtLine.querySelector('input').value||'',
										version:versionExtLine.querySelector('input').value||'',
									});
									var files={character:[],card:[],skill:[],audio:[]};
									for(var i in dash1.content.image){
										files.character.push(i);
									}
									for(var i in dash1.content.audio){
										files.audio.push('audio/die/'+i);
									}
									for(var i in dash2.content.image){
										files.card.push(i);
									}
									for(var i in dash3.content.audio){
										files.skill.push(i);
									}
									str+=',files:'+JSON.stringify(files);
									str+='}';
									var extension={'extension.js':'game.import("extension",function(lib,game,ui,get,ai,_status){return '+str+'})'};
									for(var i in dash1.content.image){
										extension[i]=dash1.content.image[i];
									}
									for(var i in dash1.content.audio){
										extension['audio/die/'+i]=dash1.content.audio[i];
									}
									for(var i in dash2.content.image){
										extension[i]=dash2.content.image[i];
									}
									game.readFile('LICENSE',function(data){
										extension['LICENSE']=data;
										game.writeFile(data,'extension/'+page.currentExtension,'LICENSE',function(){})
										if(exportext){
											var proexport=function(){
												game.importExtension(extension,null,page.currentExtension,{
													intro:introExtLine.querySelector('input').value||'',
													author:authorExtLine.querySelector('input').value||'',
													netdisk:diskExtLine.querySelector('input').value||'',
													forum:forumExtLine.querySelector('input').value||'',
													version:versionExtLine.querySelector('input').value||'',
												});
											};
											if(game.getFileList){
												game.getFileList('extension/'+page.currentExtension,function(folders,files){
													extension._filelist=files;
													proexport();
												});
											}
											else{
												proexport();
											}
										}
										else{
											game.importExtension(extension,function(){
												exportExtLine.style.display='';
											});
										}
									},function(){
										alert('许可证文件丢失,无法导出扩展');
									});
								},500);
							};
							var buttonConfirm=document.createElement('button');
							buttonConfirm.innerHTML='确定';
							buttonConfirm.style.marginLeft='5px';
							buttonConfirm.onclick=buttonConfirmOnclick;
							inputExtLine.appendChild(buttonConfirm);
							var buttonRename=document.createElement('button');
							buttonRename.innerHTML='选项';
							buttonRename.style.marginLeft='2px';
							buttonRename.style.marginRight='2px';
							buttonRename.style.display='none';
							buttonRename.onclick=function(){
								inputExtSpan.style.display='';
								inputExtName.style.display='';
								authorExtLine.style.display='';
								introExtLine.style.display='';
								forumExtLine.style.display='';
								diskExtLine.style.display='';
								versionExtLine.style.display='';
								okExtLine.style.display='block';
								inputExtLine.style.padding='20px 10px 10px 10px';
								inputExtName.disabled=false;
								buttonRename.style.display='none';
								buttonSave.style.display='none';
								buttonReset.style.display='none';
								buttonExport.style.display='none';
								inputExtSpan.innerHTML='扩展名称:';
								inputExtName.style.width='100px';
								inputExtName.style.textAlign='';

								dashboard.style.display='none';
							};
							inputExtLine.appendChild(buttonRename);
							var buttonReset=document.createElement('button');
							buttonReset.innerHTML='重置';
							buttonReset.style.marginLeft='2px';
							buttonReset.style.marginRight='2px';
							buttonReset.style.display='none';
							buttonReset.onclick=function(){
								if(confirm('当前扩展将被清除,是否确定?')){
									game.editExtension();
								}
							};
							inputExtLine.appendChild(buttonReset);
							var buttonSave=document.createElement('button');
							buttonSave.innerHTML='保存';
							buttonSave.style.marginLeft='2px';
							buttonSave.style.marginRight='2px';
							buttonSave.style.display='none';
							buttonSave.onclick=function(){
								dash1.link.classList.remove('active');
								dash2.link.classList.remove('active');
								dash3.link.classList.remove('active');
								dash4.link.classList.remove('active');
								processExtension();
							};
							inputExtLine.appendChild(buttonSave);
							var buttonExport=document.createElement('button');
							buttonExport.innerHTML='导出';
							buttonExport.style.marginLeft='2px';
							buttonExport.style.marginRight='2px';
							buttonExport.style.display='none';
							buttonExport.onclick=function(){
								function oldExport(){
									processExtension(true);
									if(lib.config.show_extensionshare){
										shareExtLine.style.display='';
									}
								}
								if(typeof game.readFile=='function'&&
									window.noname_shijianInterfaces&&
									typeof window.noname_shijianInterfaces.shareExtensionWithPassWordAsync=='function'&&
									confirm('是否使用诗笺版自带的导出功能来导出扩展?')){
									const extName=inputExtName.value;
									if (!extName) {
										alert('未检测到扩展名,将使用无名杀自带的导出功能');
										oldExport();
										return;
									}
									game.readFile(`extension/${extName}/extension.js`, () => {
										const pwd=prompt("请输入压缩包密码,不设密码直接点确定");
										let result;
										if(pwd===''||pwd=== null){
											window.noname_shijianInterfaces.shareExtensionAsync(extName);
										}else{
											window.noname_shijianInterfaces.shareExtensionWithPassWordAsync(extName, pwd);
										}
									},()=>{
										alert('未检测到扩展文件,将使用无名杀自带的导出功能');
										oldExport();
									});
								}else{
									oldExport();
								}
							};
							inputExtLine.appendChild(buttonExport);
							var exportExtLine=ui.create.div(pageboard);
							exportExtLine.style.display='none';
							exportExtLine.style.width='calc(100% - 40px)';
							exportExtLine.style.textAlign='left';
							exportExtLine.style.marginBottom='5px';
							if(lib.device=='ios'){
								exportExtLine.innerHTML='已保存。退出游戏并重新打开后生效<span class="closenode">×</span>';
								exportExtLine.querySelectorAll('span')[0].onclick=function(){
									exportExtLine.style.display='none';
								};
							}
							else{
								exportExtLine.innerHTML='重启后生效。<span class="hrefnode">立即重启</span><span class="closenode">×</span>';
								exportExtLine.querySelectorAll('span')[0].onclick=game.reload;
								exportExtLine.querySelectorAll('span')[1].onclick=function(){
									exportExtLine.style.display='none';
								};
							}


							var shareExtLine=ui.create.div(pageboard);
							shareExtLine.style.display='none';
							shareExtLine.style.width='calc(100% - 40px)';
							shareExtLine.style.textAlign='left';
							shareExtLine.style.marginBottom='5px';
							shareExtLine.innerHTML='已导出扩展。<span class="hrefnode">分享扩展</span><span class="closenode">×</span>';
							shareExtLine.querySelectorAll('span')[0].onclick = function () {
								//这个链接404了
								//game.open('https://tieba.baidu.com/p/5439380222');
								//无名杀贴吧首页
								game.open('https://tieba.baidu.com/f?ie=utf-8&kw=%E6%97%A0%E5%90%8D%E6%9D%80');
							};
							shareExtLine.querySelectorAll('span')[1].onclick=function(){
								shareExtLine.style.display='none';
							};

							var dashboard=ui.create.div(pageboard);
							var clickDash=function(){
								ui.create.templayer();
								pageboard.hide();
								this.link.show();
								if(this.link.init){
									this.link.init();
								}
							};
							var createDash=function(str1,str2,node){
								var dash=ui.create.div('.menubutton.large.dashboard');
								dashboard.appendChild(dash);
								page.appendChild(node);
								dash.link=node;
								node.link=dash;
								dash.listen(clickDash);
								lib.setScroll(node);
								ui.create.div('',str1,dash);
								ui.create.div('',str2,dash);
							};
							var dash1=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								var currentButton=null;
								page.init=function(){
									if(!page.querySelector('.button.character')){
										toggle.classList.add('on');
										newCharacter.style.display='';
									}
								};
								var updateButton=function(){
									var name=page.querySelector('input.new_name').value;
									if(!name){
										editnode.classList.add('disabled');
										return;
									}
									name=name.split('|');
									name=name[0];
									if(currentButton){
										if(currentButton.link!=name){
											if(lib.character[name]||page.content.pack.character[name]){
												editnode.classList.add('disabled');
												return;
											}
										}
									}
									else{
										if(lib.character[name]||page.content.pack.character[name]){
											editnode.classList.add('disabled');
											return;
										}
									}
									if(!fakeme.image){
										if(!page.content.image[name+'.jpg']){
											editnode.classList.add('disabled');
											return;
										}
									}
									editnode.classList.remove('disabled');
								};
								var clickButton=lib.gnc.of(function*(){
									if(currentButton==this){
										resetEditor();
										return;
									}
									resetEditor();
									currentButton=this;
									toggle.classList.add('on');
									newCharacter.style.display='';
									fakeme.classList.add('inited');
									fakeme.style.backgroundImage=this.style.backgroundImage;
									if(page.content.pack.translate[this.link]!=this.link){
										newCharacter.querySelector('.new_name').value=this.link+'|'+page.content.pack.translate[this.link];
									}
									else{
										newCharacter.querySelector('.new_name').value=this.link;
									}
									var info=page.content.pack.character[this.link];
									newCharacter.querySelector('.new_hp').value=info[2];
									sexes.value=info[0];
									groups.value=info[1];
									if(info[4]){
										for(var i=0;i<options.childNodes.length-1;i++){
											if(options.childNodes[i].lastChild&&info[4].contains(options.childNodes[i].lastChild.name)){
												options.childNodes[i].lastChild.checked=true;
											}
											else if(options.childNodes[i].lastChild){
												options.childNodes[i].lastChild.checked=false;
											}
										}
										for(var i=0;i<info[4].length;i++){
											if(info[4][i].startsWith('des:')){
												newCharacter.querySelector('.new_des').value=info[4][i].slice(4);
											}
											if(info[4][i].startsWith('die:')){
												var dieaudionode=newCharacter.querySelector('.die_audio');
												dieaudionode.file={
													name:info[4][i].slice(info[4][i].lastIndexOf('/')+1)
												};
												yield new Promise(resolve=>{
													if(typeof game.readFile=='function'){
														game.readFile(info[4][i].slice(4).replace('ext:','extension/'),arraybuffer=>{
															dieaudionode.arrayBuffer=arraybuffer;
															resolve();
														},()=>{
															console.warn(`未找到${info[4][i].slice(4).replace('ext:','extension/')}阵亡配音`);
															resolve();
														});
													}else{
														game.getDB('image',info[4][i].slice(7)).then(octetStream=>{
															dieaudionode.arrayBuffer=octetStream;
															resolve();
														},()=>{
															console.warn(`未找到${info[4][i].slice(4)}阵亡配音`);
															resolve();
														});
													}
												});
											}
										}
									}

									var skills=info[3];
									for(var i=0;i<skills.length;i++){
										var node=document.createElement('button');
										node.skill=skills[i];
										node.onclick=deletenode;
										node.innerHTML=lib.translate[skills[i]];
										skillList.firstChild.appendChild(node);
									}

									toggle.innerHTML='编辑武将 <div>&gt;</div>';
									editnode.innerHTML='编辑武将';
									editnode.classList.remove('disabled');
									delnode.innerHTML='删除';
									delnode.button=this;
								});
								var createButton=function(name,image){
									var button=ui.create.div('.button.character');
									button.link=name;
									button.image=image;
									button.style.backgroundImage='url('+image+')';
									button.style.backgroundSize='cover';
									button.listen(clickButton);
									button.classList.add('noclick');
									button.nodename=ui.create.div(button,'.name',get.verticalStr(page.content.pack.translate[name]));
									button.nodename.style.top='8px';
									page.insertBefore(button,page.childNodes[1]);
								}
								page.reset=function(name){
									resetEditor();
									var buttons=page.querySelectorAll('.button.character');
									var list=[];
									for(var i=0;i<buttons.length;i++){
										list.push(buttons[i]);
									}
									for(var i=0;i<list.length;i++){
										list[i].remove();
									}
									if(lib.extensionPack[name]){
										page.content.pack=lib.extensionPack[name].character||{
											character:{},
											translate:{}
										};
										page.content.image={};
										for(var i in page.content.pack.character){
											var file=i+'.jpg';
											var loadImage=function(file,data){
												var img = new Image();
												img.crossOrigin = 'Anonymous';
												img.onload = function() {
													var canvas = document.createElement('CANVAS');
													var ctx = canvas.getContext('2d');
													var dataURL;
													canvas.height = this.height;
													canvas.width = this.width;
													ctx.drawImage(this, 0, 0);
													canvas.toBlob(function(blob){
														var fileReader = new FileReader();
														fileReader.onload = function(e)
														{
															page.content.image[file]=e.target.result;
														};
														fileReader.readAsArrayBuffer(blob, "UTF-8");
													});
												};
												img.src=data;
											}
											if(game.download){
												var url=lib.assetURL+'extension/'+name+'/'+file;
												createButton(i,url);
												if(lib.device=='ios'||lib.device=='android'){
													window.resolveLocalFileSystemURL(lib.assetURL+'extension/'+name,function(entry){
														entry.getFile(file,{},function(fileEntry){
															fileEntry.file(function(fileToLoad){
																var fileReader = new FileReader();
																fileReader.onload = function(e){
																	page.content.image[file]=e.target.result;
																};
																fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
															});
														});
													});
												}
												else{
													loadImage(file,url);
												}
											}
											else game.getDB('image',`extension-${name}:${file}`).then(value=>{
												createButton(i,value);
												loadImage(file,value);
											});
										}
									}
									else{
										page.content={
											pack:{
												character:{},
												translate:{}
											},
											image:{},
											audio:{}
										};
										toggle.classList.add('on');
										newCharacter.style.display='';
									}
								};
								ui.create.div('.config.more','<div style="transform:none;margin-right:3px">←</div>返回',page,function(){
									ui.create.templayer();
									page.hide();
									pageboard.show();
								});
								page.content={
									pack:{
										character:{},
										translate:{}
									},
									image:{},
									audio:{}
								};
								var newCharacter;
								var toggle=ui.create.div('.config.more.on','创建武将 <div>&gt;</div>',page,function(){
									this.classList.toggle('on');
									if(this.classList.contains('on')){
										newCharacter.style.display='';
									}
									else{
										newCharacter.style.display='none';
									}
								});
								var resetEditor=function(){
									currentButton=null;
									toggle.classList.remove('on');
									newCharacter.style.display='none';
									fakeme.classList.remove('inited');
									delete fakeme.image;
									delete fakeme.image64;
									fakeme.style.backgroundImage='';
									var inputs=newCharacter.querySelectorAll('input');
									for(var i=0;i<inputs.length;i++){
										inputs[i].value='';
									}
									inputs=newCharacter.querySelectorAll('textarea');
									for(var i=0;i<inputs.length;i++){
										inputs[i].value='';
									}
									skillList.firstChild.innerHTML='';
									toggle.innerHTML='创建武将 <div>&gt;</div>';
									editnode.innerHTML='创建武将';
									editnode.classList.add('disabled');
									delnode.innerHTML='取消';
									delete delnode.button;
								}

								newCharacter=ui.create.div('.new_character',page);
								var fakeme=ui.create.div('.avatar',newCharacter);

								var input=document.createElement('input');
								input.type='file';
								input.accept='image/*';
								input.className='fileinput';
								input.onchange=function(){
									var fileToLoad=input.files[0];
									if(fileToLoad){
										var fileReader = new FileReader();
										fileReader.onload = function(fileLoadedEvent)
										{
											var data = fileLoadedEvent.target.result;
											fakeme.style.backgroundImage='url('+data+')';
											fakeme.image64=data;
											fakeme.classList.add('inited');
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												fakeme.image=fileLoadedEvent.target.result;
												updateButton();
											};
											fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
										};
										fileReader.readAsDataURL(fileToLoad, "UTF-8");
									}
								}
								fakeme.appendChild(input);

								ui.create.div('.select_avatar','选择头像',fakeme);

								ui.create.div('.indent','姓名:<input class="new_name" type="text">',newCharacter).style.paddingTop='8px';
								ui.create.div('.indent','介绍:<input class="new_des" type="text">',newCharacter).style.paddingTop='8px';
								ui.create.div('.indent','体力:<input class="new_hp" type="text" placeholder="体/限/甲">',newCharacter).style.paddingTop='8px';
								newCharacter.querySelector('input.new_name').onblur=updateButton;
								var sexes=ui.create.selectlist([
									['male','男'],
									['female','女'],
									['double','双性'],
									['none','无']
								],null,ui.create.div('.indent','性别:',newCharacter));
								var grouplist=lib.group.map((group,i)=>[lib.group[i],get.translation(lib.group[i])]);
								var groups=ui.create.selectlist(grouplist,null,ui.create.div('.indent','势力:',newCharacter));
								var dieaudio=ui.create.div('.die_audio',newCharacter,{textAlign:'left'});
								var dieaudiolabel=ui.create.node('label','阵亡配音:',dieaudio);
								var dieaudioUpload=dieaudio.appendChild(document.createElement('input'));
								dieaudioUpload.type='file';
								dieaudioUpload.accept='audio/*';
								dieaudioUpload.style.width='calc(100% - 100px)';
								dieaudioUpload.onchange=function(){
									var fileToLoad=dieaudioUpload.files[0];
									if(fileToLoad){
										console.log(fileToLoad);
										var fileReader=new FileReader();
										fileReader.onload=function(fileLoadedEvent){
											var data=fileLoadedEvent.target.result;
											var blob=new Blob([data]);
											dieaudio.file=fileToLoad;
											dieaudio.arrayBuffer=data;
											dieaudio.blob=blob;
											var new_name=newCharacter.querySelector('input.new_name');
											dieaudioUpload.style.display='none';
											dieaudiopreview.style.display=
											dieaudiocancel.style.display='';
											dieaudiotag.src=window.URL.createObjectURL(blob);
										};
										fileReader.readAsArrayBuffer(fileToLoad);
									}
								};
								var dieaudiotag=ui.create.node('audio',dieaudio);
								var dieaudiopreview=ui.create.node('button',dieaudio,()=>{
									if(dieaudiotag.error){
										alert('您使用的客户端不支持预览此音频!')
									} else dieaudiotag.play();
								});
								dieaudiopreview.innerHTML='播放';
								dieaudiopreview.style.display='none';
								var dieaudiocancel=ui.create.node('button',dieaudio,()=>{
									dieaudiopreview.style.display='none';
									dieaudiocancel.style.display='none';
									if(dieaudio.blob){
										window.URL.revokeObjectURL(dieaudio.blob);
										dieaudiotag.src=null;
										delete dieaudio.file;
										delete dieaudio.arrayBuffer;
										delete dieaudio.blob;
									}
									dieaudioUpload.value='';
									dieaudioUpload.style.display='';
								});
								dieaudiocancel.innerHTML='取消';
								dieaudiocancel.style.display='none';
								var options=ui.create.div('.add_skill.options','<span>主公<input type="checkbox" name="zhu"></span><span>BOSS<input type="checkbox" name="boss"></span><span>仅点将可用<input type="checkbox" name="forbidai"></span><br><span>隐匿技<input type="checkbox" name="hiddenSkill"></span><br>',newCharacter);
								var addSkill=ui.create.div('.add_skill','添加技能<br>',newCharacter);
								var list=[];
								for(var i in lib.character){
									if(lib.character[i][3].length){
										list.push([i,lib.translate[i]]);
									}
								}
								list.sort(function(a,b){
									a=a[0];b=b[0];
									var aa=a,bb=b;
									if(aa.includes('_')){
										aa=aa.slice(aa.indexOf('_')+1);
									}
									if(bb.includes('_')){
										bb=bb.slice(bb.indexOf('_')+1);
									}
									if(aa!=bb){
										return aa>bb?1:-1;
									}
									return a>b?1:-1;
								});
								var list2=[];
								var skills=lib.character[list[0][0]][3];
								for(var i=0;i<skills.length;i++){
									list2.push([skills[i],lib.translate[skills[i]]]);
								}
								list.unshift(['current_extension','此扩展']);

								var selectname=ui.create.selectlist(list,list[1],addSkill);
								page.selectname=selectname;
								selectname.onchange=function(){
									skillopt.innerHTML='';
									if(this.value=='current_extension'){
										for(var i in dash3.content.pack.skill){
											var option=document.createElement('option');
											option.value=i;
											option.innerHTML=dash3.content.pack.translate[i];
											skillopt.appendChild(option);
										}
									}
									else{
										var skills=lib.character[this.value][3];
										for(var i=0;i<skills.length;i++){
											var option=document.createElement('option');
											option.value=skills[i];
											option.innerHTML=lib.translate[skills[i]];
											skillopt.appendChild(option);
										}
									}
								};
								selectname.style.maxWidth='85px';
								var skillopt=ui.create.selectlist(list2,list2[0],addSkill);
								skillopt.style.maxWidth='60px';
								page.skillopt=skillopt;
								var addSkillButton=document.createElement('button');
								addSkillButton.innerHTML='添加';
								addSkill.appendChild(addSkillButton);
								page.addSkillButton=addSkillButton;
								var deletenode=function(){
									this.remove();
								}
								addSkillButton.onclick=function(){
									for(var i=0;i<skillList.firstChild.childNodes.length;i++){
										if(skillList.firstChild.childNodes[i].skill==skillopt.value) return alert(selectname.value=='current_extension'?'此扩展还未添加技能':'此武将没有技能可添加');
									}
									//无技能时
									if(!skillopt.value||skillopt.childElementCount==0) return;
									var node=document.createElement('button');
									node.skill=skillopt.value;
									node.onclick=deletenode;
									for(var i=0;i<skillopt.childElementCount;i++){
										if(skillopt.childNodes[i].value==skillopt.value){
											node.innerHTML=skillopt.childNodes[i].innerHTML;break;
										}
									}
									skillList.firstChild.appendChild(node);
								};
								var createSkillButton=document.createElement('button');
								createSkillButton.innerHTML='创建';
								createSkillButton.style.marginLeft='3px';
								addSkill.appendChild(createSkillButton);
								createSkillButton.onclick=function(){
									ui.create.templayer();
									page.hide();
									dash3.show();
									dash3.fromchar='add';
									dash3.toggle.classList.add('on');
									dash3.newSkill.style.display='';
								};
								page.updateSkill=function(){
									for(var i=0;i<skillList.firstChild.childNodes.length;i++){
										var node=skillList.firstChild.childNodes[i];
										var skill=skillList.firstChild.childNodes[i].skill;
										if(dash3.content.pack.skill[skill]){
											node.innerHTML=dash3.content.pack.translate[skill];
										}
										else if(lib.skill[skill]){
											node.innerHTML=lib.translate[skill];
										}
										else{
											node.remove();i--;
										}
									}
								};
								var skillList=ui.create.div('.skill_list',newCharacter);
								ui.create.div(skillList);
								var editnode=ui.create.div('.menubutton.large.disabled','创建武将',ui.create.div(skillList),function(){
									var name=page.querySelector('input.new_name').value;
									if(!name){
										alert('请填写武将名\n提示:武将名格式为id+|+中文名,其中id必须惟一');
										return;
									}
									name=name.split('|');
									var translate=name[1]||name[0];
									name=name[0];
									if(currentButton){
										if(currentButton.link!=name){
											if(lib.character[name]||page.content.pack.character[name]){
												alert('武将名与现有武将重复,请更改\n提示:武将名格式为id+|+中文名,其中id必须惟一');
												return;
											}
											page.content.image[name+'.jpg']=page.content.image[currentButton.link+'.jpg'];
											delete page.content.image[currentButton.link+'.jpg'];
											delete page.content.pack.character[currentButton.link];
											delete page.content.pack.translate[currentButton.link];
											currentButton.link=name;
										}
									}
									else{
										if(lib.character[name]||page.content.pack.character[name]){
											alert('武将名与现有武将重复,请更改\n提示:武将名格式为id+|+中文名,其中id必须惟一');
											return;
										}
									}
									if(fakeme.image){
										page.content.image[name+'.jpg']=fakeme.image;
									}
									else{
										if(!page.content.image[name+'.jpg']){
											alert('请选择武将头像');
											return;
										}
									}
									var hp=page.querySelector('input.new_hp').value;
									//体力支持‘Infinity,∞,无限’表示无限
									if(['Infinity','∞','无限'].includes(hp)) hp=Infinity;
									else if(hp.indexOf('/')==-1) hp=parseInt(hp)||1;
									var skills=[];
									for(var i=0;i<skillList.firstChild.childNodes.length;i++){
										skills.add(skillList.firstChild.childNodes[i].skill);
									}
									var tags=[];
									for(var i=0;i<options.childNodes.length-1;i++){
										if(options.childNodes[i].lastChild&&options.childNodes[i].lastChild.checked){
											tags.push(options.childNodes[i].lastChild.name);
										}
									}
									if(tags.contains('boss')){
										tags.add('bossallowed');
									}
									var des=page.querySelector('input.new_des').value;
									if(des){
										tags.add('des:'+des);
									}
									//阵亡配音
									if(dieaudio.file&&dieaudio.arrayBuffer){
										var audioname=name+dieaudio.file.name.slice(dieaudio.file.name.indexOf('.'));
										tags.add(`die:${typeof game.readFile=='function'?'ext':'db'}:audio/die/${audioname}`);
										page.content.audio[audioname]=dieaudio.arrayBuffer;
									}

									page.content.pack.translate[name]=translate;
									page.content.pack.character[name]=[sexes.value,groups.value,hp,skills,tags];
									if(this.innerHTML=='创建武将'){
										createButton(name,fakeme.image64);
									}
									else if(currentButton){
										if(fakeme.image64){
											currentButton.image=fakeme.image64;
											currentButton.style.backgroundImage='url('+fakeme.image64+')';
										}
										currentButton.nodename.innerHTML=get.verticalStr(translate);
									}
									resetEditor();
									dash1.link.classList.add('active');
								});
								var delnode=ui.create.div('.menubutton.large','取消',editnode.parentNode,function(){
									if(this.innerHTML=='删除'){
										this.button.remove();
										var name=this.button.link;
										delete dash1.content.pack.character[name];
										delete dash1.content.pack.translate[name];
										delete dash1.content.image[name];
										delete dash1.content.audio[name];
										dash1.link.classList.add('active');
									}
									resetEditor();
								});
								delnode.style.marginLeft='13px';

								return page;
							}());
							var dash2=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								var currentButton=null;
								page.init=function(){
									if(!page.querySelector('.button.card')){
										toggle.classList.add('on');
										newCard.style.display='';
									}
								};
								var updateButton=function(){
									var name=page.querySelector('input.new_name').value;
									if(!name){
										editnode.classList.add('disabled');
										return;
									}
									name=name.split('|');
									name=name[0];
									if(currentButton){
										if(currentButton.link!=name){
											if(lib.card[name]||page.content.pack.card[name]){
												editnode.classList.add('disabled');
												return;
											}
										}
									}
									else{
										if(lib.card[name]||page.content.pack.card[name]){
											editnode.classList.add('disabled');
											return;
										}
									}
									if(!fakeme.image&&!fakeme.classList.contains('inited')){
										editnode.classList.add('disabled');
										return;
									}
									editnode.classList.remove('disabled');
								};
								var clickButton=function(){
									if(currentButton==this){
										resetEditor();
										return;
									}
									resetEditor();
									currentButton=this;
									toggle.classList.add('on');
									newCard.style.display='';
									fakeme.classList.add('inited');
									delete fakeme.image;
									delete fakeme.image64;
									if(this.classList.contains('fullskin')){
										fakeme.imagenode.style.backgroundImage=this.imagenode.style.backgroundImage;
										fakeme.classList.add('fullskin');
									}
									else{
										fakeme.style.backgroundImage=this.style.backgroundImage;
										fakeme.classList.remove('fullskin');
									}
									if(page.content.pack.translate[this.link]!=this.link){
										newCard.querySelector('.new_name').value=this.link+'|'+page.content.pack.translate[this.link];
									}
									else{
										newCard.querySelector('.new_name').value=this.link;
									}
									newCard.querySelector('.new_description').value=page.content.pack.translate[this.link+'_info'];
									var info=page.content.pack.card[this.link];
									container.code='card='+get.stringify(info);

									toggle.innerHTML='编辑卡牌 <div>&gt;</div>';
									editnode.innerHTML='编辑卡牌';
									editnode.classList.remove('disabled');
									delnode.innerHTML='删除';
									delnode.button=this;
								}
								var createButton=function(name,image,fullskin){
									var button=ui.create.div('.button.card');
									button.link=name;
									button.image=image;
									button.imagenode=ui.create.div('.image',button);
									if(image){
										if(fullskin){
											button.imagenode.style.backgroundImage='url('+image+')';
											button.style.backgroundImage='';
											button.style.backgroundSize='';
											button.classList.add('fullskin');
										}
										else{
											button.style.color='white';
											button.style.textShadow='black 0 0 2px';
											button.imagenode.style.backgroundImage='';
											button.style.backgroundImage='url('+image+')';
											button.style.backgroundSize='cover';
										}
									}
									button.listen(clickButton);
									button.classList.add('noclick');
									button.nodename=ui.create.div(button,'.name',get.verticalStr(page.content.pack.translate[name]));
									page.insertBefore(button,page.childNodes[1]);
								}
								page.reset=function(name){
									resetEditor();
									var buttons=page.querySelectorAll('.button.card');
									var list=[];
									for(var i=0;i<buttons.length;i++){
										list.push(buttons[i]);
									}
									for(var i=0;i<list.length;i++){
										list[i].remove();
									}
									if(lib.extensionPack[name]){
										page.content.pack=lib.extensionPack[name].card||{
											card:{},
											translate:{}
										};
										page.content.image={};
										if(Array.isArray(page.content.pack.list)){
											for(var i=0;i<page.content.pack.list.length;i++){
												var card=page.content.pack.list[i];
												var node=document.createElement('button');
												node.innerHTML=page.content.pack.translate[card[2]]+' '+lib.translate[card[0]]+card[1];
												node.name=card[2];
												node.link=card;
												pile.appendChild(node);
												node.onclick=function(){
													this.remove();
												}
											}
										}
										for(var i in page.content.pack.card){
											var file;
											var fullskin=page.content.pack.card[i].fullskin?true:false;
											if(fullskin){
												file=i+'.png';
											}
											else{
												file=i+'.jpg';
											}
											var loadImage=function(file,data){
												var img = new Image();
												img.crossOrigin = 'Anonymous';
												img.onload = function() {
													var canvas = document.createElement('CANVAS');
													var ctx = canvas.getContext('2d');
													var dataURL;
													canvas.height = this.height;
													canvas.width = this.width;
													ctx.drawImage(this, 0, 0);
													canvas.toBlob(function(blob){
														var fileReader = new FileReader();
														fileReader.onload = function(e)
														{
															page.content.image[file]=e.target.result;
														};
														fileReader.readAsArrayBuffer(blob, "UTF-8");
													});
												};
												img.src=data;
											}
											if(game.download){
												var url=lib.assetURL+'extension/'+name+'/'+file;
												createButton(i,url,fullskin);
												if(lib.device=='ios'||lib.device=='android'){
													window.resolveLocalFileSystemURL(lib.assetURL+'extension/'+name,function(entry){
														entry.getFile(file,{},function(fileEntry){
															fileEntry.file(function(fileToLoad){
																var fileReader = new FileReader();
																fileReader.onload = function(e){
																	page.content.image[file]=e.target.result;
																};
																fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
															});
														});
													});
												}
												else{
													loadImage(file,url);
												}
											}
											else game.getDB('image',`extension-${name}:${file}`).then(value=>{
												createButton(i,value,fullskin);
												loadImage(file,value);
											});
										}
									}
									else{
										page.content={
											pack:{
												card:{},
												translate:{}
											},
											image:{}
										};
										toggle.classList.add('on');
										newCard.style.display='';
									}
									updatePile();
								};
								ui.create.div('.config.more.margin-bottom','<div style="transform:none;margin-right:3px">←</div>返回',page,function(){
									ui.create.templayer();
									page.hide();
									pageboard.show();
								});
								page.content={
									pack:{
										card:{},
										translate:{},
										list:[]
									},
									image:{}
								};
								var newCard;
								var toggle=ui.create.div('.config.more.on','创建卡牌 <div>&gt;</div>',page,function(){
									this.classList.toggle('on');
									if(this.classList.contains('on')){
										newCard.style.display='';
									}
									else{
										newCard.style.display='none';
									}
								});
								var resetEditor=function(){
									currentButton=null;
									toggle.classList.remove('on');
									newCard.style.display='none';
									fakeme.classList.remove('inited');
									fakeme.classList.add('fullskin');
									delete fakeme.image;
									delete fakeme.image64;
									fakeme.style.backgroundImage='';
									fakeme.imagenode.style.backgroundImage='';
									var inputs=newCard.querySelectorAll('input');
									for(var i=0;i<inputs.length;i++){
										inputs[i].value='';
									}
									toggle.innerHTML='创建卡牌 <div>&gt;</div>';
									editnode.innerHTML='创建卡牌';
									editnode.classList.add('disabled');
									delnode.innerHTML='取消';
									delete delnode.button;
									container.code='card={\n    \n}\n\n\/*\n示例:\ncard={\n    type:"basic",\n    enable:true,\n    filterTarget:true,\n    content:function(){\n        target.draw()\n    },\n    ai:{\n        order:1,\n        result:{\n            target:1\n        }\n    }\n}\n此例的效果为目标摸一张牌\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';
								}

								newCard=ui.create.div('.new_character',page);
								newCard.style.height='173px';
								var fakeme=ui.create.div('.card.fullskin',newCard);

								var input=document.createElement('input');
								input.type='file';
								input.accept='image/*';
								input.className='fileinput';
								input.onchange=function(){
									var fileToLoad=input.files[0];
									if(fileToLoad){
										var fileReader = new FileReader();
										var fullimage=(fileToLoad.name.includes('.jpg'));
										fileReader.onload = function(fileLoadedEvent)
										{
											var data = fileLoadedEvent.target.result;
											if(fullimage){
												fakeme.imagenode.style.backgroundImage='';
												fakeme.style.backgroundImage='url('+data+')';
												fakeme.classList.remove('fullskin');
											}
											else{
												fakeme.style.backgroundImage='';
												fakeme.imagenode.style.backgroundImage='url('+data+')';
												fakeme.classList.add('fullskin');
											}
											fakeme.image64=data;
											fakeme.classList.add('inited');
											var fileReader = new FileReader();
											fileReader.onload = function(fileLoadedEvent)
											{
												fakeme.image=fileLoadedEvent.target.result;
												updateButton();
											};
											fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
										};
										fileReader.readAsDataURL(fileToLoad, "UTF-8");
									}
								}
								fakeme.appendChild(input);

								fakeme.imagenode=ui.create.div('.image',fakeme);
								ui.create.div('.name','选择背景',fakeme);

								ui.create.div('.indent','名称:<input class="new_name" type="text">',newCard).style.paddingTop='8px';
								ui.create.div('.indent','描述:<input class="new_description" type="text">',newCard).style.paddingTop='6px';
								newCard.querySelector('input.new_name').onblur=updateButton;
								var codeButton=document.createElement('button');
								newCard.appendChild(codeButton);
								codeButton.innerHTML='编辑代码';
								codeButton.style.left='123px';
								codeButton.style.top='66px';
								codeButton.style.position='absolute';

								var citeButton=document.createElement('button');
								newCard.appendChild(citeButton);
								citeButton.innerHTML='引用代码';
								citeButton.style.left='123px';
								citeButton.style.top='90px';
								citeButton.style.position='absolute';
								citeButton.onclick=function(){
									codeButton.style.display='none';
									citeButton.style.display='none';
									selectname.style.display='';
									confirmcontainer.style.display='';
								}

								var list=[];
								for(var i in lib.card){
									if(lib.translate[i]){
										list.push([i,lib.translate[i]]);
									}
								}
								list.sort(function(a,b){
									a=a[0];b=b[0];
									var aa=a,bb=b;
									if(aa.includes('_')){
										aa=aa.slice(aa.indexOf('_')+1);
									}
									if(bb.includes('_')){
										bb=bb.slice(bb.indexOf('_')+1);
									}
									if(aa!=bb){
										return aa>bb?1:-1;
									}
									return a>b?1:-1;
								});
								var selectname=ui.create.selectlist(list,list[0],newCard);
								selectname.style.left='123px';
								selectname.style.top='66px';
								selectname.style.position='absolute';
								selectname.style.display='none';

								var confirmcontainer=ui.create.div(newCard);
								confirmcontainer.style.left='123px';
								confirmcontainer.style.top='90px';
								confirmcontainer.style.position='absolute';
								confirmcontainer.style.display='none';

								var citeconfirm=document.createElement('button');
								citeconfirm.innerHTML='引用';
								confirmcontainer.appendChild(citeconfirm);
								citeconfirm.onclick=function(){
									codeButton.style.display='';
									citeButton.style.display='';
									selectname.style.display='none';
									confirmcontainer.style.display='none';
									container.code='card='+get.stringify(lib.card[selectname.value]);
									codeButton.onclick.call(codeButton);
									if(lib.translate[selectname.value+'_info']){
										newCard.querySelector('input.new_description').value=lib.translate[selectname.value+'_info'];
									}
								}

								var citecancel=document.createElement('button');
								citecancel.innerHTML='取消';
								citecancel.style.marginLeft='3px';
								confirmcontainer.appendChild(citecancel);
								citecancel.onclick=function(){
									codeButton.style.display='';
									citeButton.style.display='';
									selectname.style.display='none';
									confirmcontainer.style.display='none';
								}

								codeButton.onclick=function(){
									var node=container;
									ui.window.classList.add('shortcutpaused');
									ui.window.classList.add('systempaused');
									window.saveNonameInput=saveInput;
									if(node.aced){
										ui.window.appendChild(node);
										node.editor.setValue(node.code,1);
									}
									else if(lib.device=='ios'){
										ui.window.appendChild(node);
										if(!node.textarea){
											var textarea=document.createElement('textarea');
											editor.appendChild(textarea);
											node.textarea=textarea;
											lib.setScroll(textarea);
										}
										node.textarea.value=node.code;
									}
									else{
										if(!window.CodeMirror){
											lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,editor));
											lib.init.css(lib.assetURL+'layout/default','codemirror');
										}
										else{
											lib.codeMirrorReady(node,editor);
										}
									}
								}

								var container=ui.create.div('.popup-container.editor');
								var saveInput=function(){
									var code;
									if(container.editor){
										code=container.editor.getValue();
									}
									else if(container.textarea){
										code=container.textarea.value;
									}
									try{
										var card=null;
										eval(code);
										if(card==null||typeof card!='object'){
											throw('err');
										}
									}
									catch(e){
										if(e=='err'){
											alert('代码格式有错误,请对比示例代码仔细检查');
										}
										else{
											var tip=lib.getErrorTip(e)||'';
											alert('代码语法有错误,请仔细检查('+e+')'+tip);
										}
										window.focus();
										if(container.editor){
											container.editor.focus();
										}
										else if(container.textarea){
											container.textarea.focus();
										}
										return;
									}
									dash2.link.classList.add('active');
									ui.window.classList.remove('shortcutpaused');
									ui.window.classList.remove('systempaused');
									container.delete();
									container.code=code;
									delete window.saveNonameInput;
								};
								var editor=ui.create.editor(container,saveInput);
								container.code='card={\n    \n}\n\n\/*\n示例:\ncard={\n    type:"basic",\n    enable:true,\n    filterTarget:true,\n    content:function(){\n        target.draw()\n    },\n    ai:{\n        order:1,\n        result:{\n            target:1\n        }\n    }\n}\n此例的效果为目标摸一张牌\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';

								var editnode=ui.create.div('.menubutton.large.new_card.disabled','创建卡牌',newCard,function(){
									var name=page.querySelector('input.new_name').value;
									if(!name){
										alert('请填写卡牌名\n提示:卡牌名格式为id+|+中文名,其中id必须惟一');
										return;
									}
									name=name.split('|');
									var translate=name[1]||name[0];
									var info=page.querySelector('input.new_description').value;
									name=name[0];
									if(currentButton){
										if(currentButton.link!=name){
											if(lib.card[name]||page.content.pack.card[name]){
												alert('卡牌名与现有卡牌重复,请更改\n提示:卡牌名格式为id+|+中文名,其中id必须惟一');
												return;
											}
											var extname;
											if(currentButton.classList.contains('fullskin')){
												extname='.png';
											}
											else{
												extname='.jpg';
											}
											page.content.image[name+extname]=page.content.image[currentButton.link+extname];
											delete page.content.image[currentButton.link+extname];
											delete page.content.pack.card[currentButton.link];
											delete page.content.pack.translate[currentButton.link];
											delete page.content.pack.translate[currentButton.link+'_info'];
											currentButton.link=name;
										}
									}
									else{
										if(lib.card[name]||page.content.pack.card[name]){
											alert('卡牌名与现有卡牌重复,请更改\n提示:卡牌名格式为id+|+中文名,其中id必须惟一');
											return;
										}
									}
									if(fakeme.image){
										if(fakeme.classList.contains('fullskin')){
											page.content.image[name+'.png']=fakeme.image;
											delete page.content.image[name+'.jpg'];
										}
										else{
											page.content.image[name+'.jpg']=fakeme.image;
											delete page.content.image[name+'.png'];
										}
									}
									else if(!fakeme.classList.contains('inited')){
										alert('请选择一个卡牌背景');
										return;
									}
									page.content.pack.translate[name]=translate;
									page.content.pack.translate[name+'_info']=info;
									try{
										var card=null;
										eval(container.code);
										if(card==null||typeof card!='object'){
											throw('err');
										}
										page.content.pack.card[name]=card;
									}
									catch(e){
										page.content.pack.card[name]={};
									}
									if(fakeme.classList.contains('inited')){
										if(fakeme.classList.contains('fullskin')){
											page.content.pack.card[name].fullskin=true;
											delete page.content.pack.card[name].fullimage;
										}
										else{
											page.content.pack.card[name].fullimage=true;
											delete page.content.pack.card[name].fullskin;
										}
									}
									if(this.innerHTML=='创建卡牌'){
										createButton(name,fakeme.image64,fakeme.classList.contains('fullskin'));
									}
									else if(currentButton){
										if(fakeme.image64){
											if(fakeme.classList.contains('fullskin')){
												currentButton.style.color='';
												currentButton.style.textShadow='';
												currentButton.imagenode.style.backgroundImage='url('+fakeme.image64+')';
												currentButton.style.backgroundImage='';
												currentButton.style.backgroundSize='';
												currentButton.classList.add('fullskin');
											}
											else{
												currentButton.style.color='white';
												currentButton.style.textShadow='black 0 0 2px';
												currentButton.imagenode.style.backgroundImage='';
												currentButton.style.backgroundImage='url('+fakeme.image64+')';
												currentButton.style.backgroundSize='cover';
												currentButton.classList.remove('fullskin');
											}
										}
										currentButton.nodename.innerHTML=get.verticalStr(translate);
									}
									resetEditor();
									updatePile();
									dash2.link.classList.add('active');
								});
								var delnode=ui.create.div('.menubutton.large.new_card_delete','取消',editnode.parentNode,function(){
									if(this.innerHTML=='删除'){
										this.button.remove();
										var name=this.button.link;
										delete dash2.content.pack.card[name];
										delete dash2.content.pack.translate[name];
										delete dash2.content.pack.translate[name+'_info'];
										delete dash2.content.image[name];
										updatePile();
										dash2.link.classList.add('active');
									}
									resetEditor();
								});

								var editPile;
								var toggle2=ui.create.div('.config.more','编辑牌堆 <div>&gt;</div>',page,function(){
									this.classList.toggle('on');
									if(this.classList.contains('on')){
										editPile.style.display='';
									}
									else{
										editPile.style.display='none';
									}
								});

								editPile=ui.create.div('.edit_pile',page);
								editPile.style.display='none';


								var cardpileadd=ui.create.div('.config.toggle.cardpilecfg.cardpilecfgadd',editPile);
								var pile=ui.create.div(editPile);
								page.pile=pile;
								var cardpileaddname=document.createElement('select');
								var updatePile=function(){
									cardpileaddname.innerHTML='';
									var list=[];
									var list2=[];
									for(var i in page.content.pack.card){
										list.push([i,page.content.pack.translate[i]]);
										list2.push(i);
									}
									if(list.length){
										toggle2.style.display='';
										if(toggle2.classList.contains('on')){
											editPile.style.display='';
										}
										else{
											editPile.style.display='none';
										}
										for(var i=0;i<list.length;i++){
											var option=document.createElement('option');
											option.value=list[i][0];
											option.innerHTML=list[i][1];
											cardpileaddname.appendChild(option);
										}
										for(var i=0;i<pile.childNodes.length;i++){
											if(!list2.contains(pile.childNodes[i].name)){
												pile.childNodes[i].remove();i--;
											}
										}
									}
									else{
										toggle2.style.display='none';
										editPile.style.display='none';
										pile.innerHTML='';
									}
								};
								updatePile();
								cardpileadd.appendChild(cardpileaddname);
								cardpileaddname.style.width='75px';
								cardpileaddname.style.marginRight='2px';
								cardpileaddname.style.marginLeft='-1px';
								var cardpileaddsuit=ui.create.selectlist([
									['heart','红桃'],
									['diamond','方片'],
									['club','梅花'],
									['spade','黑桃'],
								],null,cardpileadd);
								cardpileaddsuit.style.width='53px';
								cardpileaddsuit.style.marginRight='2px';
								var cardpileaddnumber=ui.create.selectlist([
									1,2,3,4,5,6,7,8,9,10,11,12,13
								],null,cardpileadd);
								cardpileaddnumber.style.width='43px';
								cardpileaddnumber.style.marginRight='2px';
								var button=document.createElement('button');
								button.innerHTML='确定';
								button.style.width='40px';
								button.onclick=function(){
									var card=[
										cardpileaddsuit.value,
										cardpileaddnumber.value,
										cardpileaddname.value,
									];
									var node=document.createElement('button');
									node.innerHTML=page.content.pack.translate[card[2]]+' '+lib.translate[card[0]]+card[1];
									node.name=card[2];
									node.link=card;
									pile.appendChild(node);
									node.onclick=function(){
										this.remove();
									}
								};
								cardpileadd.appendChild(button);
								cardpileadd.style.whiteSpace='nowrap';
								cardpileadd.style.position='relative';
								cardpileadd.style.right='-4px';

								return page;
							}());
							var dash3=(function(){
								var page=ui.create.div('.hidden.menu-buttons.new_skill');
								var updateButton=function(){
									var name=page.querySelector('input.new_name').value;
									if(!name){
										editnode.classList.add('disabled');
										return;
									}
									name=name.split('|');
									name=name[0];
									if(currentButton){
										if(currentButton.link!=name){
											if(lib.skill[name]||page.content.pack.skill[name]){
												editnode.classList.add('disabled');
												return;
											}
										}
									}
									else{
										if(lib.skill[name]||page.content.pack.skill[name]){
											editnode.classList.add('disabled');
											return;
										}
									}
									editnode.classList.remove('disabled');
								};
								page.init=function(){
									if(!page.querySelector('.menubutton:not(.large)')){
										toggle.classList.add('on');
										newSkill.style.display='';
									}
								};
								page.reset=function(name){
									resetEditor();
									var buttons=page.querySelectorAll('.menubutton:not(.large)');
									var list=[];
									for(var i=0;i<buttons.length;i++){
										list.push(buttons[i]);
									}
									for(var i=0;i<list.length;i++){
										list[i].remove();
									}
									if(lib.extensionPack[name]){
										page.content.pack=lib.extensionPack[name].skill||{
											skill:{},
											translate:{}
										};
										page.content.audio={};
										for(var i in page.content.pack.skill){
											createButton(i);
										}
										dash1.updateSkill();
									}
									else{
										page.content={
											pack:{
												skill:{},
												translate:{}
											},
											audio:{}
										};
										toggle.classList.add('on');
										newSkill.style.display='';
									}
								};
								ui.create.div('.config.more.margin-bottom','<div style="transform:none;margin-right:3px">←</div>返回',page,function(){
									ui.create.templayer();
									page.hide();
									if(page.fromchar){
										dash1.show();
										delete page.fromchar;
									}
									else{
										pageboard.show();
									}
								});
								var currentButton=null;
								var clickButton=function(){
									if(currentButton==this){
										resetEditor();
										return;
									}
									resetEditor();
									currentButton=this;
									toggle.classList.add('on');
									newSkill.style.display='';
									if(page.content.pack.translate[this.link]!=this.link){
										newSkill.querySelector('.new_name').value=this.link+'|'+page.content.pack.translate[this.link];
									}
									else{
										newSkill.querySelector('.new_name').value=this.link;
									}
									newSkill.querySelector('.new_description').value=page.content.pack.translate[this.link+'_info'];
									var info=page.content.pack.skill[this.link];
									container.code='skill='+get.stringify(info);

									toggle.innerHTML='编辑技能 <div>&gt;</div>';
									editnode.innerHTML='编辑技能';
									editnode.classList.remove('disabled');
									delnode.button=this;
									delnode.innerHTML='删除';
								}
								var createButton=function(name){
									var button=ui.create.div('.menubutton');
									button.link=name;
									button.innerHTML=page.content.pack.translate[name];
									button.listen(clickButton);
									page.insertBefore(button,page.childNodes[1]);
								}
								var newSkill;
								var toggle=ui.create.div('.config.more.on','创建技能 <div>&gt;</div>',page,function(){
									this.classList.toggle('on');
									if(this.classList.contains('on')){
										newSkill.style.display='';
									}
									else{
										newSkill.style.display='none';
									}
								});
								page.toggle=toggle;
								var resetEditor=function(){
									currentButton=null;
									toggle.classList.remove('on');
									newSkill.style.display='none';
									var inputs=newSkill.querySelectorAll('input');
									for(var i=0;i<inputs.length;i++){
										inputs[i].value='';
									}
									var inputs=newSkill.querySelectorAll('textarea');
									for(var i=0;i<inputs.length;i++){
										inputs[i].value='';
									}
									toggle.innerHTML='创建技能 <div>&gt;</div>';
									editnode.innerHTML='创建技能';
									editnode.classList.add('disabled');
									delnode.innerHTML='取消';
									delete delnode.button;
									container.code='skill={\n    \n}\n\n\/*\n示例:\nskill={\n    trigger:{player:"phaseJieshuBegin"},\n    frequent:true,\n    content:function(){\n        player.draw()\n    }\n}\n此例为闭月代码\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';
									if(page.fromchar=='add'){
										page.fromchar=true;
									}
								}

								newSkill=ui.create.div('.new_character.new_skill',page);
								page.newSkill=newSkill;
								var namenode=ui.create.div('.config','名称:<input class="new_name" type="text" style="width:120px"></input>',newSkill);
								var descnode=ui.create.div('.config','描述:<input class="new_description" type="text" style="width:120px"></input>',newSkill);
								namenode.querySelector('input.new_name').onblur=updateButton;
								var commandline=ui.create.div('.config',newSkill);
								var editbutton=document.createElement('button');
								editbutton.innerHTML='编辑代码';
								commandline.appendChild(editbutton);
								editbutton.onclick=function(){
									var node=container;
									ui.window.classList.add('shortcutpaused');
									ui.window.classList.add('systempaused');
									window.saveNonameInput=saveInput;
									if(node.aced){
										ui.window.appendChild(node);
										node.editor.setValue(node.code,1);
									}
									else if(lib.device=='ios'){
										ui.window.appendChild(node);
										if(!node.textarea){
											var textarea=document.createElement('textarea');
											editor.appendChild(textarea);
											node.textarea=textarea;
											lib.setScroll(textarea);
										}
										node.textarea.value=node.code;
									}
									else{
										if(!window.CodeMirror){
											lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,editor));
											lib.init.css(lib.assetURL+'layout/default','codemirror');
										}
										else{
											lib.codeMirrorReady(node,editor);
										}
									}
								}

								var container=ui.create.div('.popup-container.editor');
								var saveInput=function(){
									var code;
									if(container.editor){
										code=container.editor.getValue();
									}
									else if(container.textarea){
										code=container.textarea.value;
									}
									try{
										var skill=null;
										eval(code);
										if(skill==null||typeof skill!='object'){
											throw('err');
										}
									}
									catch(e){
										if(e=='err'){
											alert('代码格式有错误,请对比示例代码仔细检查');
										}
										else{
											var tip=lib.getErrorTip(e)||'';
											alert('代码语法有错误,请仔细检查('+e+')'+tip);
										}
										window.focus();
										if(container.editor){
											container.editor.focus();
										}
										else if(container.textarea){
											container.textarea.focus();
										}
										return;
									}
									dash3.link.classList.add('active');
									ui.window.classList.remove('shortcutpaused');
									ui.window.classList.remove('systempaused');
									container.delete();
									container.code=code;
									delete window.saveNonameInput;
								};
								var editor=ui.create.editor(container,saveInput);
								container.code='skill={\n    \n}\n\n\/*\n示例:\nskill={\n    trigger:{player:"phaseJieshuBegin"},\n    frequent:true,\n    content:function(){\n        player.draw()\n    }\n}\n此例为闭月代码\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';

								var citebutton=document.createElement('button');
								citebutton.innerHTML='引用代码';
								commandline.appendChild(citebutton);
								citebutton.onclick=function(){
									editbutton.style.display='none';
									citebutton.style.display='none';
									selectname.style.display='';
									skillopt.style.display='';
									addSkillButton.style.display='';
									cancelSkillButton.style.display='';
								}

								var list=[];
								for(var i in lib.character){
									if(lib.character[i][3].length){
										list.push([i,lib.translate[i]]);
									}
								}
								list.sort(function(a,b){
									a=a[0];b=b[0];
									var aa=a,bb=b;
									if(aa.includes('_')){
										aa=aa.slice(aa.indexOf('_')+1);
									}
									if(bb.includes('_')){
										bb=bb.slice(bb.indexOf('_')+1);
									}
									if(aa!=bb){
										return aa>bb?1:-1;
									}
									return a>b?1:-1;
								});
								list.push(['others','其它']);
								var list2=[];
								var skills=lib.character[list[0][0]][3];
								for(var i=0;i<skills.length;i++){
									list2.push([skills[i],lib.translate[skills[i]]]);
								}
								var selectname=ui.create.selectlist(list,list[0],commandline);
								var list3=[];
								for(var i in lib.skill){
									if(i!='global'&&!get.is.empty(lib.skill[i])&&!lib.skilllist.contains(i)){
										list3.push(i);
									}
								}
								list3.sort(function(a,b){
									return a>b?1:-1;
								});
								selectname.onchange=function(){
									var skills;
									skillopt.innerHTML='';
									if(this.value=='others'){
										skills=list3;
										for(var i=0;i<skills.length;i++){
											var option=document.createElement('option');
											option.value=skills[i];
											option.innerHTML=skills[i];
											skillopt.appendChild(option);
										}
									}
									else{
										skills=lib.character[this.value][3];
										for(var i=0;i<skills.length;i++){
											var option=document.createElement('option');
											option.value=skills[i];
											option.innerHTML=lib.translate[skills[i]];
											skillopt.appendChild(option);
										}
									}
								};
								selectname.style.display='none';
								selectname.style.maxWidth='80px';
								var skillopt=ui.create.selectlist(list2,list2[0],commandline);
								skillopt.style.display='none';
								skillopt.style.maxWidth='60px';
								var addSkillButton=document.createElement('button');
								addSkillButton.style.display='none';
								addSkillButton.innerHTML='引用';
								commandline.appendChild(addSkillButton);
								addSkillButton.onclick=function(){
									editbutton.style.display='';
									citebutton.style.display='';
									selectname.style.display='none';
									skillopt.style.display='none';
									addSkillButton.style.display='none';
									cancelSkillButton.style.display='none';
									container.code='skill='+get.stringify(lib.skill[skillopt.value]);
									editbutton.onclick.call(editbutton);
									if(lib.translate[skillopt.value+'_info']){
										newSkill.querySelector('input.new_description').value=lib.translate[skillopt.value+'_info'];
									}
								}
								var cancelSkillButton=document.createElement('button');
								cancelSkillButton.style.display='none';
								cancelSkillButton.innerHTML='取消';
								commandline.appendChild(cancelSkillButton);
								cancelSkillButton.onclick=function(){
									editbutton.style.display='';
									citebutton.style.display='';
									selectname.style.display='none';
									skillopt.style.display='none';
									addSkillButton.style.display='none';
									cancelSkillButton.style.display='none';
								}

								var editnode=ui.create.div('.menubutton.large.new_skill.disabled','创建技能',function(){
									var name=page.querySelector('input.new_name').value;
									if(!name){
										alert('请填写技能名\n提示:技能名格式为id+|+中文名,其中id必须惟一');
										return;
									}
									name=name.split('|');
									var translate=name[1]||name[0];
									var info=page.querySelector('input.new_description').value;
									name=name[0];
									if(currentButton){
										if(currentButton.link!=name){
											if(lib.skill[name]||page.content.pack.skill[name]){
												alert('技能名与现有技能重复,请更改\n提示:技能名格式为id+|+中文名,其中id必须惟一');
												return;
											}
											delete page.content.pack.skill[currentButton.link];
											delete page.content.pack.translate[currentButton.link];
											delete page.content.pack.translate[currentButton.link+'_info'];
											currentButton.link=name;
										}
									}
									else{
										if(lib.skill[name]||page.content.pack.skill[name]){
											alert('技能名与现有技能重复,请更改\n提示:技能名格式为id+|+中文名,其中id必须惟一');
											return;
										}
									}
									page.content.pack.translate[name]=translate;
									page.content.pack.translate[name+'_info']=info;
									try{
										var skill=null;
										eval(container.code);
										if(skill==null||typeof skill!='object'){
											throw('err');
										}
										page.content.pack.skill[name]=skill;
									}
									catch(e){
										page.content.pack.skill[name]={};
									}
									dash1.selectname.value='current_extension';
									dash1.selectname.onchange.call(dash1.selectname);
									if(this.innerHTML=='创建技能'){
										createButton(name);
										if(page.fromchar=='add'){
											ui.create.templayer();
											page.hide();
											dash1.show();
											dash1.skillopt.value=name;
											dash1.addSkillButton.onclick();
											delete page.fromchar;
										}
									}
									else if(currentButton){
										currentButton.innerHTML=translate;
									}
									resetEditor();
									dash3.link.classList.add('active');
									dash1.updateSkill();
								},newSkill);
								var delnode=ui.create.div('.menubutton.large.new_card_delete','取消',editnode.parentNode,function(){
									if(this.innerHTML=='删除'){
										this.button.remove();
										var name=this.button.link;
										delete dash3.content.pack.skill[name];
										delete dash3.content.pack.translate[name];
										delete dash3.content.pack.translate[name+'_info'];
										dash3.link.classList.add('active');
										if(get.is.empty(dash3.content.pack.skill)){
											dash1.selectname.value=dash1.selectname.childNodes[1].value;
										}
										dash1.selectname.onchange.call(dash1.selectname);
										dash1.updateSkill();
										resetEditor();
									}
									else if(page.fromchar=='add'){
										ui.create.templayer();
										page.hide();
										dash1.show();
										delete page.fromchar;
										setTimeout(resetEditor,600);
									}
									else{
										resetEditor();
									}
								});

								page.content={
									pack:{
										skill:{},
										translate:{}
									},
									audio:{}
								};
								return page;
							}());
							var dash4=(function(){
								var page=ui.create.div('.hidden.menu-buttons');
								ui.create.div('.config.more.margin-bottom','<div style="transform:none;margin-right:3px">←</div>返回',page,function(){
									ui.create.templayer();
									page.hide();
									pageboard.show();
								});
								page.reset=function(name){
									page.content={};
									if(lib.extensionPack[name]){
										for(var i in dashes){
											dashes[i].node.code='';
										}
										for(var i in lib.extensionPack[name].code){
											switch(typeof lib.extensionPack[name].code[i]){
												case 'function':page.content[i]=lib.extensionPack[name].code[i].toString();break;
												case 'object':page.content[i]=i+'='+get.stringify(lib.extensionPack[name].code[i]);break;
											}
										}
										for(var i in page.content){
											dashes[i].node.code=page.content[i]||'';
										}
									}
									else{
										dashes.content.node.code='function(config,pack){\n    \n}\n\n\/*\n函数执行时机为游戏数据加载之后、界面加载之前\n参数1扩展选项(见选项代码);参数2为扩展定义的武将、卡牌和技能等(可在此函数中修改)\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';
										dashes.precontent.node.code='function(){\n    \n}\n\n\/*\n函数执行时机为游戏数据加载之前,且不受禁用扩展的限制\n除添加模式外请慎用\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';
										dashes.config.node.code='config={\n    \n}\n\n\/*\n示例:\nconfig={\n    switcher_example:{\n    name:"示例列表选项",\n        init:"3",\n        item:{"1":"一","2":"二","3":"三"}\n    },\n    toggle_example:{\n        name:"示例开关选项",\n        init:true\n    }\n}\n此例中传入的主代码函数的默认参数为{switcher_example:"3",toggle_example:true}\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';
										dashes.help.node.code='help={\n    \n}\n\n\/*\n示例:\nhelp={\n    "帮助条目":"<ul><li>列表1-条目1<li>列表1-条目2</ul><ol><li>列表2-条目1<li>列表2-条目2</ul>"\n}\n帮助内容将显示在菜单-选项-帮助中\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/';
									}
								};
								var dashes={};
								var createCode=function(str1,str2,sub,func,link,str){
									var dash=ui.create.div('.menubutton.large.dashboard');
									dashes[link]=dash;
									sub.appendChild(dash);
									dash.listen(func);
									dash.link=link;
									ui.create.div('',str1,dash);
									ui.create.div('',str2,dash);
									var container=ui.create.div('.popup-container.editor');
									var saveInput=function(){
										var code;
										if(container.editor){
											code=container.editor.getValue();
										}
										else if(container.textarea){
											code=container.textarea.value;
										}
										try{
											if(link=='content'||link=='precontent'){
												var func=null;
												eval('func='+code);
												if(typeof func!='function'){
													throw('err');
												}
											}
											else if(link=='config'){
												var config=null;
												eval(code);
												if(config==null||typeof config!='object'){
													throw('err');
												}
											}
											else if(link=='help'){
												var help=null;
												eval(code);
												if(help==null||typeof help!='object'){
													throw('err');
												}
											}
										}
										catch(e){
											if(e=='err'){
												alert('代码格式有错误,请对比示例代码仔细检查');
											}
											else{
												var tip=lib.getErrorTip(e)||'';
												alert('代码语法有错误,请仔细检查('+e+')'+tip);
											}
											window.focus();
											if(container.editor){
												container.editor.focus();
											}
											else if(container.textarea){
												container.textarea.focus();
											}
											return;
										}
										dash4.link.classList.add('active');
										ui.window.classList.remove('shortcutpaused');
										ui.window.classList.remove('systempaused');
										container.delete();
										container.code=code;
										page.content[link]=code;
										delete window.saveNonameInput;
									};
									var editor=ui.create.editor(container,saveInput);
									container.code=str;
									dash.editor=editor;
									dash.node=container;
									dash.saveInput=saveInput;
									page.content[link]=str;
								};
								var clickCode=function(){
									var node=this.node;
									ui.window.classList.add('shortcutpaused');
									ui.window.classList.add('systempaused');
									window.saveNonameInput=this.saveInput;
									if(node.aced){
										ui.window.appendChild(node);
										node.editor.setValue(node.code,1);
									}
									else if(lib.device=='ios'){
										ui.window.appendChild(node);
										if(!node.textarea){
											var textarea=document.createElement('textarea');
											this.editor.appendChild(textarea);
											node.textarea=textarea;
											lib.setScroll(textarea);
										}
										node.textarea.value=node.code;
									}
									else{
										if(!window.CodeMirror){
											lib.init.js(lib.assetURL+'game','codemirror',()=>lib.codeMirrorReady(node,this.editor));
											lib.init.css(lib.assetURL+'layout/default','codemirror');
										}
										else{
											lib.codeMirrorReady(node,this.editor);
										}
									}
								};
								page.content={}
								createCode('主','主代码',page,clickCode,'content','function(config,pack){\n    \n}\n\n\/*\n函数执行时机为游戏数据加载之后、界面加载之前\n参数1扩展选项(见选项代码);参数2为扩展定义的武将、卡牌和技能等(可在此函数中修改)\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/');
								createCode('启','启动代码',page,clickCode,'precontent','function(){\n    \n}\n\n\/*\n函数执行时机为游戏数据加载之前,且不受禁用扩展的限制\n除添加模式外请慎用\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/');
								createCode('选','选项代码',page,clickCode,'config','config={\n    \n}\n\n\/*\n示例:\nconfig={\n    switcher_example:{\n        name:"示例列表选项",\n        init:"3",\n     	  item:{"1":"一","2":"二","3":"三"}\n    },\n    toggle_example:{\n        name:"示例开关选项",\n        init:true\n    }\n}\n此例中传入的主代码函数的默认参数为{switcher_example:"3",toggle_example:true}\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/');
								createCode('帮','帮助代码',page,clickCode,'help','help={\n    \n}\n\n\/*\n示例:\nhelp={\n    "帮助条目":"<ul><li>列表1-条目1<li>列表1-条目2</ul><ol><li>列表2-条目1<li>列表2-条目2</ul>"\n}\n帮助内容将显示在菜单-选项-帮助中\n导出时本段代码中的换行、缩进以及注释将被清除\n*\/');

								return page;
							}());
							createDash('将','编辑武将',dash1);
							createDash('卡','编辑卡牌',dash2);
							createDash('技','编辑技能',dash3);
							createDash('码','编辑代码',dash4);
						};
						if(!get.config('menu_loadondemand')) node._initLink();
					}());
					(function(){
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large','获取扩展',start.firstChild,clickMode);
						node.mode='get';
						var _thisUpdate=false;
						node.update=function(){
							_thisUpdate=true;
						};
						node._initLink=function(){
							node.link=page;
							page.listen(function(){
								if(!page.currenttimeout){
									var active=page.querySelector('.videonode.current');
									if(active){
										active.classList.remove('current');
									}
								}
							});
							var importextensionexpanded=false;
							page.style.paddingBottom='10px';
							var importExtension;
							var extensionNode=ui.create.div('.config.more','导入扩展 <div>&gt;</div>',page,function(){
								if(importextensionexpanded){
									this.classList.remove('on');
									importExtension.style.display='none';
								}
								else{
									this.classList.add('on');
									importExtension.style.display='';
								}
								importextensionexpanded=!importextensionexpanded;
							});
							importExtension=ui.create.div('.new_character.export.import',page);
							importExtension.style.marginLeft='5px';
							importExtension.style.marginTop='5px';
							importExtension.style.marginBottom='5px';
							importExtension.style.display='none';
							importExtension.style.width='100%';
							importExtension.style.textAlign='left';
							ui.create.div('','<input type="file" accept="application/zip" style="width:153px"><button>确定</button>',importExtension);
							ui.create.div('.config','修改下载地址',page,function(){
								alert('您可以在“设置→通用→获取扩展地址”中,修改下载扩展时所采用的地址。')
							})

							var extensionURL;
							var source=lib.config.extension_sources,index=lib.config.extension_source;
							if(source&&source[index]) extensionURL=source[index];
							else extensionURL=lib.updateURL.replace(/noname/g,'noname-extension')+'/master/';

							var reloadnode=ui.create.div('.config.toggle.pointerdiv','重新启动',page,game.reload);
							reloadnode.style.display='none';
							var placeholder=ui.create.div('.config.toggle',page);
							placeholder.style.height=0;
							placeholder.style.marginTop='5px';

							importExtension.firstChild.lastChild.onclick=function(){
								const fileToLoad=this.previousSibling.files[0];
								if(!fileToLoad) return;
								new Promise((resolve,reject)=>{
									const fileReader=new FileReader();
									fileReader.onerror=reject;
									fileReader.onload=resolve;
									fileReader.readAsArrayBuffer(fileToLoad,"UTF-8");
								}).then(progressEvent=>{
									if(game.importExtension(progressEvent.target.result,()=>{
										extensionNode.innerHTML='导入成功,3秒后将重启';
										new Promise(resolve=>setTimeout(resolve,1000)).then(()=>{
											extensionNode.innerHTML='导入成功,2秒后将重启';
											return new Promise(resolve=>setTimeout(resolve,1000));
										}).then(()=>{
											extensionNode.innerHTML='导入成功,1秒后将重启';
											return new Promise(resolve=>setTimeout(resolve,1000));
										}).then(game.reload);
									})!==false) importExtension.style.display='none';
								});
							}

							var clickExtension=function(){
								var active=this.parentNode.querySelector('.videonode.current');
								if(active&&active!=this){
									active.classList.remove('current');
								}
								this.classList.add('current');
								clearTimeout(page.currenttimeout);
								page.currenttimeout=setTimeout(function(){
									delete page.currenttimeout;
								},200);
							};
							var downloadExtension=function(e){
								if((this.innerHTML!='下载扩展'&&this.innerHTML!='更新扩展')||!window.JSZip) return;
								this.classList.remove('update');
								if(e){
									e.stopPropagation();
								}
								node.updated=true;
								var that=this;
								var list=[];
								var size=parseFloat(this.info.size)||0;
								if(size){
									if(this.info.size.includes('MB')){
										size*=1024*1024;
									}
									else if(this.info.size.includes('KB')){
										size*=1024;
									}
								}

								this.innerHTML='<span>正在下载</span><div>正在下载</div>';
								this.classList.add('nopointer');
								this.classList.add('button-downloading');
								var progress=ui.create.div('.button-progress',this);
								ui.create.div(progress);
								var url=extensionURL+this.info.name+'.zip';
								var onprogress=function(byte,total){
									if(total){
										size=total;
									}
									if(byte==-1){
										byte=size;
									}
									progress.firstChild.style.width=Math.round(100*byte/size)+'%';
								};
								var files=this.info.files||[];
								for(var i=0;i<files.length;i++){
									files[i]='extension/'+that.info.name+'/'+files[i];
								}
								game.checkFileList(files,function(){
									files.unshift('extension/'+that.info.name+'/extension.js');
									for(var i=0;i<files.length;i++){
										files[i]=extensionURL+that.info.name+'/'+files[i].slice(10+that.info.name.length+1);
									}
									var n1=0,n2=files.length;
									game.multiDownload(files,function(){
										n1++;
										onprogress(n1,n2);
									},function(e){
										game.print('下载失败:'+e.source);
									},function(){
										onprogress(-1);
										_status.importingExtension=true;
										window.game=game;
										lib.init.js(lib.assetURL+'extension/'+that.info.name,'extension',function(){
											if(!lib.config.dev) delete window.game;
											if(game.importedPack){
												var extname=game.importedPack.name;
												if(lib.config.extensions.contains(extname)){
													game.removeExtension(extname,true);
												}
												lib.config.extensions.add(extname);
												game.saveConfig('extensions',lib.config.extensions);
												game.saveConfig('extension_'+extname+'_enable',true);
												game.saveConfig('extension_'+extname+'_version',that.info.version);
												for(var i in game.importedPack.config){
													if(game.importedPack.config[i]&&game.importedPack.config[i].hasOwnProperty('init')){
														game.saveConfig('extension_'+extname+'_'+i,game.importedPack.config[i].init);
													}
												}
												reloadnode.style.display='';
												that.childNodes[0].innerHTML='安装成功';
												that.childNodes[1].innerHTML='安装成功';
												that.classList.remove('active');
												that.classList.remove('highlight');
												delete game.importedPack;
											}
											else{
												that.innerHTML='安装失败';
												that.classList.add('nopointer');
											}
											_status.importingExtension=false;
										},function(){
											that.innerHTML='下载失败';
											that.classList.add('nopointer');
											_status.importingExtension=false;
										});
									},function(current){
										return 'extension/'+current.slice(extensionURL.length);
									});
								});
							};

							node.update=function(){
								if(this.updated) return;
								if(!window.JSZip){
									lib.init.js(lib.assetURL+'game','jszip');
								}
								var toremove=[];
								for(var i=0;i<page.childElementCount;i++){
									if(page.childNodes[i].classList.contains('menubutton')||page.childNodes[i].classList.contains('loading')){
										toremove.push(page.childNodes[i]);
									}
								}
								for(var i=0;i<toremove.length;i++){
									toremove[i].remove();
								}

								var loading=ui.create.div('.loading.config.toggle','载入中...',page);
								var loaded=function(){
									var list=[];
									var extension=window.extension;
									for(var i in extension){
										extension[i].name=i;
										list.push(extension[i]);
									}
									list.randomSort();
									delete window.extension;
									loading.style.display='none';
									for(var i =0;i<list.length;i++){
										var node=ui.create.div('.videonode.menubutton.extension.large',page,clickExtension);
										ui.create.div('.caption',list[i].name,node);
										ui.create.div('.text.author','作者:'+list[i].author+'<span>('+list[i].size+')</span>',node);
										ui.create.div('.text','更新日期:'+list[i].date,node);
										ui.create.div('.text',list[i].intro,node);
										var download=ui.create.div('.menubutton.text.active','下载扩展',node.firstChild,{'zIndex':'5'});
										if(game.download){
											if(list[i].netdisk){
												var linknode=ui.create.div('.text',node);
												ui.create.node('span.hrefnode','网盘链接',function(){
													game.open(this.link);
												},linknode).link=list[i].netdisk;
												if(list[i].forum){
													ui.create.node('span',linknode).style.marginRight='10px';
													ui.create.node('span.hrefnode','参与讨论',function(){
														game.open(this.link);
													},linknode).link=list[i].forum;
												}
											}
											else if(list[i].forum){
												var linknode=ui.create.div('.text',node);
												ui.create.node('span.hrefnode','参与讨论',function(){
													game.open(this.link);
												},linknode).link=list[i].forum;
											}
											download.listen(downloadExtension);
											if(lib.config.extensions.includes(list[i].name)){
												download.classList.remove('active');
												if(lib.extensionPack[list[i].name]&&lib.extensionPack[list[i].name].version==list[i].version){
													download.classList.add('transparent2');
													download.classList.remove('active');
													download.innerHTML='已安装';
												}
												else if(lib.config['extension_'+list[i].name+'_version']!=list[i].version){
													download.innerHTML='更新扩展';
													download.classList.add('highlight');
													download.classList.add('update');
												}
												else{
													download.classList.add('transparent2');
													download.classList.remove('active');
													download.innerHTML='已安装';
												}
											}
											download.info=list[i];
										}
										else{
											if(list[i].forum){
												var linknode=ui.create.div('.text',node);
												ui.create.node('span',linknode);
												ui.create.node('span.hrefnode','参与讨论',function(){
													game.open(this.link);
												},linknode).link=list[i].forum;
											}
											download.listen(function(){
												game.open(this.link);
											});
											download.link=list[i].netdisk;
										}
									}
								};
								window.extension={};
								fetch(`${extensionURL}catalog.js`,{
									referrerPolicy:'no-referrer'
								}).then(response=>response.text()).then(eval).then(loaded).catch(reason=>{
									console.log(reason);
									delete window.extension;
									loading.innerHTML='连接失败:'+(reason instanceof Error?reason.message:String(reason));
								});
							};
							if(_thisUpdate) node.update();
						};
						if(!get.config('menu_loadondemand')) node._initLink();
					}());
					var active=start.firstChild.querySelector('.active');
					if(!active){
						active=start.firstChild.firstChild;
						active.classList.add('active');
					}
					if(!active.link) active._initLink();
					rightPane.appendChild(active.link);
					updateNodes();
				}());

				(function(){
					if(connectMenu) return;
					var start=menuxpages.shift();
					var rightPane=start.lastChild;
					var cheatButton=ui.create.div('.menubutton.round.highlight','作',start);
					cheatButton.style.display='none';
					var runButton=ui.create.div('.menubutton.round.highlight','执',start);
					runButton.style.display='none';
					var clearButton=ui.create.div('.menubutton.round.highlight','清',start);
					clearButton.style.display='none';
					clearButton.style.left='275px';
					var playButton=ui.create.div('.menubutton.round.highlight.hidden','播',start);
					playButton.style.display='none';
					playButton.style.left='215px';
					playButton.style.transition='opacity 0.3s';
					var deleteButton=ui.create.div('.menubutton.round.highlight.hidden','删',start);
					deleteButton.style.display='none';
					deleteButton.style.left='275px';
					deleteButton.style.transition='opacity 0.3s';
					var saveButton=ui.create.div('.menubutton.round.highlight.hidden','存',start);
					saveButton.style.display='none';
					saveButton.style.transition='opacity 0.3s';


					var clickMode=function(){
						if(this.classList.contains('off')) return;
						var active=this.parentNode.querySelector('.active');
						if(active===this){
							return;
						}
						if(active){
							active.classList.remove('active');
							active.link.remove();
						}
						active=this;
						this.classList.add('active');
						if(this.link) rightPane.appendChild(this.link);
						else{
							this._initLink();
							rightPane.appendChild(this.link);
						}
						if(this.type=='cheat'){
							cheatButton.style.display='';
						}
						else{
							cheatButton.style.display='none';
						}
						if(this.type=='cmd'){
							runButton.style.display='';
							clearButton.style.display='';
						}
						else{
							runButton.style.display='none';
							clearButton.style.display='none';
						}
						if(this.type=='video'){
							playButton.style.display='';
							saveButton.style.display='';
							deleteButton.style.display='';
						}
						else{
							playButton.style.display='none';
							saveButton.style.display='none';
							deleteButton.style.display='none';
						}
					};

					ui.click.consoleMenu=function(){
						ui.click.menuTab('其它');
						clickMode.call(ui.commandnode);
					};
					//更新菜单有本体函数赋值,就不要懒加载了
					(function(){
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large','更新',start.firstChild,clickMode);
						node.link=page;
						page.classList.add('menu-help');
						var ul=document.createElement('ul');
						var li1=document.createElement('li');
						var li2=document.createElement('li');
						var li3=document.createElement('li');
						const trimURL=url=>{
							const updateURLS=lib.updateURLS;
							for(const key in updateURLS){
								const updateURL=updateURLS[key];
								if(url==updateURL) return lib.configMenu.general.config.update_link.item[key];
							}
							let index=url.indexOf('://');
							if(index!=-1) url=url.slice(index+3);
							index=url.indexOf('/');
							if(index!=-1) url=url.slice(0,index);
							if(url.length>15){
								const list=url.split('.');
								if(list.length>1) list.shift();
								url=list.join('.');
							}
							if(url.length>15){
								const list=url.split('.');
								if(list.length>1) list.pop();
								url=list.join('.');
							}
							return url;
						}
						li1.innerHTML='游戏版本:'+lib.version+'<p style="margin-top:8px;white-space:nowrap"></p>';
						li2.innerHTML='素材版本:'+(lib.config.asset_version||'无')+'<p style="margin-top:8px"></p>';
						li3.innerHTML='更新地址:<span>'+trimURL(lib.config.updateURL||lib.updateURL)+'</span><p style="margin-top:8px"></p>';
						li3.style.whiteSpace='nowrap';
						li3.style.display='none';// coding

						var button1,button2,button3,button4,button5;

						game.checkForUpdate=function(forcecheck,dev){
							if(!dev&&button1.disabled){
								return;
							}
							else if(dev&&button3.disabled){
								return;
							}
							else if(!game.download){
								alert('此版本不支持游戏内更新,请手动更新');
								return;
							}
							else{
								if(dev){
									button3.innerHTML='正在检查更新';
								}
								else{
									button1.innerHTML='正在检查更新';
								}
								button3.disabled=true;
								button1.disabled=true;

								var goupdate=function(files,update){
									lib.version=update.version;
									if(update.dev&&!lib.config.debug){
										dev='nodev';
									}
									lib.init.req('game/source.js',function(){
										try{
											eval(this.responseText);
											if(!window.noname_source_list){
												throw('err');
											}
										}
										catch(e){
											alert('更新地址有误');
											console.log(e);
											return;
										}

										var updates=window.noname_source_list;
										delete window.noname_source_list;
										if(Array.isArray(files)){
											files.add('game/update.js');
											var files2=[];
											for(var i=0;i<files.length;i++){
												var str=files[i].indexOf('*');
												if(str!=-1){
													str=files[i].slice(0,str);
													files.splice(i--,1);
													for(var j=0;j<updates.length;j++){
														if(updates[j].startsWith(str)){
															files2.push(updates[j]);
														}
													}
												}
											}
											updates=files.concat(files2);
										}
										for(var i=0;i<updates.length;i++){
											if(updates[i].startsWith('theme/')&&!updates[i].includes('.css')){
												updates.splice(i--,1);
											}
											else if(updates[i].startsWith('node_modules/')&&!update.node){
												updates.splice(i--,1);
											}
										}

										if(!ui.arena.classList.contains('menupaused')){
											ui.click.configMenu();
											ui.click.menuTab('其它');
										}
										var p=button1.parentNode;
										button1.remove();
										button3.remove();
										var span=document.createElement('span');
										var n1=0;
										var n2=updates.length;
										span.innerHTML='正在下载文件('+n1+'/'+n2+')';
										p.appendChild(span);
										var finish=function(){
											span.innerHTML='游戏更新完毕('+n1+'/'+n2+')';
											p.appendChild(document.createElement('br'));
											var button=document.createElement('button');
											button.innerHTML='重新启动';
											button.onclick=game.reload;
											button.style.marginTop='8px';
											p.appendChild(button);
										}
										game.multiDownload(updates,function(){
											n1++;
											span.innerHTML='正在下载文件('+n1+'/'+n2+')';
										},function(e){
											game.print('下载失败:'+e.source);
										},function(){
											setTimeout(finish,500);
										},null,dev);
									},function(){
										alert('更新地址有误');
									},true);
								};

								lib.init.req('game/update.js',function(){
									try{
										eval(this.responseText);
										if(!window.noname_update){
											throw('err');
										}
									}
									catch(e){
										alert('更新地址有误');
										console.log(e);
										return;
									}

									var update=window.noname_update;
									delete window.noname_update;
									if(forcecheck===false){
										if(update.version==lib.config.check_version){
											return;
										}
									}
									game.saveConfig('check_version',update.version);
									var goon=true;
									if(!dev){
										if(update.version.includes('beta')||update.version==lib.version){
											goon=false;
										}
									}
									if(goon){
										var files=null;
										var version=lib.version;
										if(Array.isArray(update.dev)&&dev){
											files=update.dev;
										}
										else if(Array.isArray(update.files)&&update.update&&!dev){
											var version1=version.split('.');
											var version2=update.update.split('.');
											for(var i=0;i<version1.length&&i<version2.length;i++){
												if(version2[i]>version1[i]){
													files=false;break;
												}
												else if(version1[i]>version2[i]){
													files=update.files.slice(0);break;
												}
											}
											if(files===null){
												if(version1.length>=version2.length){
													files=update.files.slice(0);
												}
											}
										}
										var str;
										if(dev){
											str='开发版仅供测试使用,可能存在风险,是否确定更新?'
										}
										else{
											str='有新版本'+update.version+'可用,是否下载?';
										}
										if(navigator.notification&&navigator.notification.confirm){
											var str2;
											if(dev){
												str2=str;
												str='更新到开发版';
											}
											else{
												str2=update.changeLog[0];
												for(var i=1;i<update.changeLog.length;i++){
													if(update.changeLog[i].indexOf('://')==-1){
														str2+=';'+update.changeLog[i];
													}
												}
											}
											navigator.notification.confirm(
												str2,
												function(index){
													if(index==1){
														goupdate(files,update);
													}
													else{
														button1.disabled=false;
														button1.innerHTML='检查游戏更新';
														button3.disabled=false;
														button3.innerHTML='更新到开发版';
													}
												},
												str,
												['确定','取消']
											);
										}
										else{
											if(confirm(str)){
												goupdate(files,update);
											}
											else{
												button1.disabled=false;
												button1.innerHTML='检查游戏更新';
												button3.disabled=false;
												button3.innerHTML='更新到开发版';
											}
										}
									}
									else{
										alert('当前版本已是最新');
										button1.disabled=false;
										button1.innerHTML='检查游戏更新';
										button3.disabled=false;
										button3.innerHTML='更新到开发版';
									}
								},function(){
									if(forcecheck===false){
										return;
									}
									alert('连接失败');
									button1.disabled=false;
									button1.innerHTML='检查游戏更新';
									button3.disabled=false;
									button3.innerHTML='更新到开发版';
								},true);
							}
						};
						game.checkForAssetUpdate=function(type){
							if(button2.disabled){
								return;
							}
							else if(game.download){
								button2.innerHTML='正在检查更新';
								button2.disabled=true;
								lib.init.req('game/asset.js',function(){
									try{
										eval(this.responseText);
										if(!window.noname_asset_list||!window.noname_skin_list){
											throw('err');
										}
									}
									catch(e){
										alert('更新地址有误');
										console.log(e);
										return;
									}

									var updates=window.noname_asset_list;
									delete window.noname_asset_list;
									var skins=window.noname_skin_list;
									delete window.noname_skin_list;
									var asset_version=updates.shift();

									var skipcharacter=[],skipcard=['tiesuo_mark','shield'];
									if(!lib.config.asset_full){
										for(var i=0;i<lib.config.all.sgscharacters.length;i++){
											var pack=lib.characterPack[lib.config.all.sgscharacters[i]];
											for(var j in pack){
												skipcharacter.add(j);
											}
										}
										for(var i=0;i<lib.config.all.sgscards.length;i++){
											var pack=lib.cardPack[lib.config.all.sgscards[i]];
											if(pack){
												skipcard=skipcard.concat(pack);
											}
										}
									}
									for(var i=0;i<updates.length;i++){
										switch(updates[i].slice(0,5)){
											case 'image':{
												if(!lib.config.asset_full){
													if(!lib.config.asset_image){
														updates.splice(i--,1);
													}
													else{
														if(updates[i].startsWith('image/character')){
															if(updates[i].indexOf('jun_')!=16&&updates[i].indexOf('gz_')!=16&&!skipcharacter.contains(updates[i].slice(16,updates[i].lastIndexOf('.')))){
																updates.splice(i--,1);
															}
														}
														else if(updates[i].startsWith('image/card')){
															let cardname=updates[i].slice(11,updates[i].lastIndexOf('.'));
															if(lib.card[cardname]&&!skipcard.contains(cardname)){
																updates.splice(i--,1);
															}
														}
														else if(updates[i].startsWith('image/mode/stone')){
															updates.splice(i--,1);
														}
													}
												}
												break;
											}
											case 'audio':{
												if(!lib.config.asset_audio){
													updates.splice(i--,1);
												}
												break;
											}
											case 'font/':{
												if(!lib.config.asset_font){
													updates.splice(i--,1);
												}
											}
										}
									}
									if(lib.config.asset_skin){
										for(var i in skins){
											for(var j=1;j<=skins[i];j++){
												updates.push('image/skin/'+i+'/'+j+'.jpg');
											}
										}
									}
									if(!ui.arena.classList.contains('menupaused')){
										ui.click.configMenu();
										ui.click.menuTab('其它');
									}

									var proceed=function(){
										if(updates.length==0){
											game.print(updates);
											game.saveConfig('asset_version',asset_version);
											alert('素材已是最新');
											button2.disabled=false;
											button2.innerHTML='检查素材更新';
											return;
										}
										var p=button2.parentNode;
										button2.remove();
										var span=document.createElement('span');
										span.style.whiteSpace='nowrap';
										var n1=0;
										var n2=updates.length;
										span.innerHTML='正在下载素材('+n1+'/'+n2+')';
										span1.remove();
										span2.remove();
										span2_check.remove();
										span3.remove();
										span3_check.remove();
										span4.remove();
										span4_check.remove();
										span5.remove();
										span5_check.remove();
										span6.remove();
										span6_check.remove();
										span2_br.remove();
										span3_br.remove();
										span4_br.remove();
										span5_br.remove();
										span6_br.remove();
										p.appendChild(span);

										var br6=ui.create.node('br');
										var span7=ui.create.div('.hrefnode','详细信息');
										span7.style.marginTop='6px';
										span7.listen(ui.click.consoleMenu);
										p.appendChild(br6);
										p.appendChild(span7);

										var finish=function(){
											if(n1==n2){
												game.saveConfig('asset_version',asset_version);
											}
											span.innerHTML='素材更新完毕('+n1+'/'+n2+')';
											p.appendChild(document.createElement('br'));
											var button=document.createElement('button');
											button.innerHTML='重新启动';
											button.onclick=game.reload;
											button.style.marginTop='8px';
											p.appendChild(button);
										}
										game.multiDownload(updates,function(){
											n1++;
											span.innerHTML='正在下载素材('+n1+'/'+n2+')';
										},function(e){
											game.print('下载失败:'+e.source);
										},function(){
											setTimeout(finish,500);
										});
									};
									game.checkFileList(updates,proceed);
								},function(){
									alert('连接失败');
									button2.disabled=false;
									button2.innerHTML='检查素材更新';
								},true);
							}
							else{
								alert('此版本不支持游戏内更新素材,请手动更新');
							}
						};

						button1=document.createElement('button');
						button1.innerHTML='检查游戏更新';
						button1.onclick=game.checkForUpdate;
						li1.lastChild.appendChild(button1);

						button3=document.createElement('button');
						button3.innerHTML='更新到开发版';
						button3.style.marginLeft='5px';
						button3.onclick=function(){
							game.checkForUpdate(null,true);
						};
						// if(lib.config.dev){
						//     li1.lastChild.appendChild(button3);
						// }

						(function(){
							var updatep1=li1.querySelector('p');
							var updatep2=li2;
							var updatep3=li3;
							var updatep4=node;
							var updatepx=ui.create.node('p');
							li1.appendChild(updatepx);
							updatepx.style.display='none';
							updatepx.style.whiteSpace='nowrap';
							updatepx.style.marginTop='8px';
							var buttonx=ui.create.node('button','访问项目主页',function(){
								window.open('https://github.com/libccy/noname');
							});
							updatepx.appendChild(buttonx);
							ui.updateUpdate=function(){
								if(!game.download){
									updatep1.style.display='none';
									updatep2.style.display='none';
									updatep3.style.display='none';
									updatepx.style.display='';
									updatep4.innerHTML='关于';
								}
								else{
									updatep1.style.display='';
									updatep2.style.display='';
									updatep3.style.display='none'; // coding
									updatepx.style.display='none';
									updatep4.innerHTML='更新';
								}
							}
							ui.updateUpdate();
						}());

						button4=document.createElement('button');
						button4.innerHTML='设置更新地址';
						button4.onclick=function(){
							game.prompt('设置更新地址',function(str){
								if(str){
									game.saveConfig('updateURL',str);
									li3.querySelector('span').innerHTML=trimURL(str);
									button5.style.display='';
									button6.style.display='none';
								}
							});
						};
						// li3.lastChild.appendChild(button4);

						var button6=document.createElement('button');
						button6.innerHTML='设为备用镜像';
						button6.style.display='none';// coding
						// button6.style.marginLeft='5px';
						button6.onclick=function(){
							game.saveConfig('updateURL',lib.mirrorURL);
							button5.style.display='';
							button6.style.display='none';
							li3.querySelector('span').innerHTML=trimURL(lib.mirrorURL);
						};
						li3.lastChild.appendChild(button6);

						button5=document.createElement('button');
						button5.innerHTML='设为默认镜像';
						// button5.style.marginLeft='5px';
						button5.onclick=function(){
							game.saveConfig('updateURL');
							button5.style.display='none';
							button6.style.display='';
							li3.querySelector('span').innerHTML=trimURL(lib.updateURL);
						};
						li3.lastChild.appendChild(button5);
						if(!lib.config.updateURL){
							button5.style.display='none';
						}
						else{
							button6.style.display='none';
						}

						button2=document.createElement('button');
						button2.innerHTML='检查素材更新';
						button2.onclick=game.checkForAssetUpdate;
						li2.lastChild.appendChild(button2);

						var span1=ui.create.div('.config.more','选项 <div>&gt;</div>');
						span1.style.fontSize='small';
						span1.style.display='inline';
						span1.toggle=function(){
							if(!this.classList.toggle('on')){
								game.saveConfig('asset_toggle_off',true);
								span2.style.display='none';
								span2_br.style.display='none';
								span2_check.style.display='none';
								span3.style.display='none';
								span3_br.style.display='none';
								span3_check.style.display='none';
								span4.style.display='none';
								span4_br.style.display='none';
								span4_check.style.display='none';
								span5.style.display='none';
								span5_br.style.display='none';
								span5_check.style.display='none';
								span6.style.display='none';
								span6_br.style.display='none';
								span6_check.style.display='none';
							}
							else{
								game.saveConfig('asset_toggle_off');
								span2.style.display='';
								span2_br.style.display='';
								span2_check.style.display='';
								span3.style.display='';
								span3_br.style.display='';
								span3_check.style.display='';
								span4.style.display='';
								span4_br.style.display='';
								span4_check.style.display='';
								span5.style.display='';
								span5_br.style.display='';
								span5_check.style.display='';
								span6.style.display='';
								span6_br.style.display='';
								span6_check.style.display='';
							}
						};
						span1.listen(span1.toggle);
						li2.lastChild.appendChild(span1);

						var span6_br=ui.create.node('br');
						li2.lastChild.appendChild(span6_br);

						var span5=ui.create.div('','图片素材(精简,126MB)');
						span5.style.fontSize='small';
						span5.style.lineHeight='16px';
						var span5_check=document.createElement('input');
						span5_check.type='checkbox';
						span5_check.style.marginLeft='5px';
						if(lib.config.asset_image){
							span5_check.checked=true;
						}
						span5_check.onchange=function(){
							game.saveConfig('asset_image',this.checked);
						}
						var span2_br=ui.create.node('br');

						var span4=ui.create.div('','字体素材(48MB)');
						span4.style.fontSize='small';
						span4.style.lineHeight='16px';
						li2.lastChild.appendChild(span4);
						var span4_check=document.createElement('input');
						span4_check.type='checkbox';
						span4_check.style.marginLeft='5px';
						if(lib.config.asset_font){
							span4_check.checked=true;
						}
						span4_check.onchange=function(){
							game.saveConfig('asset_font',this.checked);
						}
						li2.lastChild.appendChild(span4_check);
						var span3_br=ui.create.node('br');
						li2.lastChild.appendChild(span3_br);

						var span3=ui.create.div('','音效素材(125MB)');
						span3.style.fontSize='small';
						span3.style.lineHeight='16px';
						li2.lastChild.appendChild(span3);
						var span3_check=document.createElement('input');
						span3_check.type='checkbox';
						span3_check.style.marginLeft='5px';
						if(lib.config.asset_audio){
							span3_check.checked=true;
						}
						span3_check.onchange=function(){
							game.saveConfig('asset_audio',this.checked);
						}
						li2.lastChild.appendChild(span3_check);
						var span4_br=ui.create.node('br');
						li2.lastChild.appendChild(span4_br);

						var span2=ui.create.div('','皮肤素材(351MB)');
						span2.style.fontSize='small';
						span2.style.lineHeight='16px';
						li2.lastChild.appendChild(span2);
						var span2_check=document.createElement('input');
						span2_check.type='checkbox';
						span2_check.style.marginLeft='5px';
						if(lib.config.asset_skin){
							span2_check.checked=true;
						}
						span2_check.onchange=function(){
							game.saveConfig('asset_skin',this.checked);
						}
						li2.lastChild.appendChild(span2_check);
						var span5_br=ui.create.node('br');
						li2.lastChild.appendChild(span5_br);


						li2.lastChild.appendChild(span5);
						li2.lastChild.appendChild(span5_check);
						li2.lastChild.appendChild(span2_br);

						var span6=ui.create.div('','图片素材(完整,203MB)');
						span6.style.fontSize='small';
						span6.style.lineHeight='16px';
						li2.lastChild.appendChild(span6);
						var span6_check=document.createElement('input');
						span6_check.type='checkbox';
						span6_check.style.marginLeft='5px';
						if(lib.config.asset_full){
							span6_check.checked=true;
						}
						span6_check.onchange=function(){
							game.saveConfig('asset_full',this.checked);
						}
						li2.lastChild.appendChild(span6_check);

						span2.style.display='none';
						span2_br.style.display='none';
						span2_check.style.display='none';
						span3.style.display='none';
						span3_br.style.display='none';
						span3_check.style.display='none';
						span4.style.display='none';
						span4_br.style.display='none';
						span4_check.style.display='none';
						span5.style.display='none';
						span5_br.style.display='none';
						span5_check.style.display='none';
						span6.style.display='none';
						span6_br.style.display='none';
						span6_check.style.display='none';

						ul.appendChild(li1);
						ul.appendChild(li2);
						ul.appendChild(li3);
						page.appendChild(ul);


						if(!lib.config.asset_toggle_off){
							span1.toggle();
						}
					}());
					(function(){
						var norow2=function(){
							var node=currentrow1;
							if(!node) return false;
							return node.innerHTML=='横置'||node.innerHTML=='翻面'||node.innerHTML=='换人'||node.innerHTML=='复活';
						};
						var checkCheat=function(){
							if(norow2()){
								for(var i=0;i<row2.childElementCount;i++){
									row2.childNodes[i].classList.remove('selectedx');
									row2.childNodes[i].classList.add('unselectable');
								}
							}
							else{
								for(var i=0;i<row2.childElementCount;i++){
									row2.childNodes[i].classList.remove('unselectable');
								}
							}
							if(currentrow1&&currentrow1.innerHTML=='复活'){
								for(var i=0;i<row3.childNodes.length;i++){
									if(row3.childNodes[i].dead){
										row3.childNodes[i].style.display='';
									}
									else{
										row3.childNodes[i].style.display='none';
										row3.childNodes[i].classList.remove('glow');
									}
									row3.childNodes[i].classList.remove('unselectable');
								}
							}
							else{
								for(var i=0;i<row3.childElementCount;i++){
									if(currentrow1&&currentrow1.innerHTML=='换人'&&row3.childNodes[i].link==game.me){
										row3.childNodes[i].classList.add('unselectable');
									}
									else{
										row3.childNodes[i].classList.remove('unselectable');
									}
									if(!row3.childNodes[i].dead){
										row3.childNodes[i].style.display='';
									}
									else{
										row3.childNodes[i].style.display='none';
										row3.childNodes[i].classList.remove('glow');
									}
								}
							}
							if(currentrow1&&(currentrow2||norow2())&&row3.querySelector('.glow')){
								cheatButton.classList.add('glowing');
								return true;
							}
							else{
								cheatButton.classList.remove('glowing');
								return false;
							}
						}
						cheatButton.listen(function(){
							if(checkCheat()){
								var num;
								if(currentrow2){
									switch(currentrow2.innerHTML){
										case '一':num=1;break;
										case '二':num=2;break;
										case '三':num=3;break;
										case '四':num=4;break;
										case '五':num=5;break;
									}
								}
								var targets=[];
								var buttons=row3.querySelectorAll('.glow');
								for(var i=0;i<buttons.length;i++){
									targets.push(buttons[i].link);
								}
								while(targets.length){
									var target=targets.shift();
									switch(currentrow1.innerHTML){
										case '伤害':target.damage(num,'nosource');break;
										case '回复':target.recover(num,'nosource');break;
										case '摸牌':target.draw(num);break;
										case '弃牌':target.discard(target.getCards('he').randomGets(num));break;
										case '横置':target.link();break;
										case '翻面':target.turnOver();break;
										case '复活':target.revive(target.maxHp);break;
										case '换人':{
											if(_status.event.isMine()){
												if(!ui.auto.classList.contains('hidden')){
													setTimeout(function(){
														ui.click.auto();
														setTimeout(function(){
															ui.click.auto();
															game.swapPlayer(target);
														},500);
													});
												}
											}
											else{
												game.swapPlayer(target);
											}
											break;
										}
									}
								}
								if(ui.coin){
									game.changeCoin(-20);
								}
								clickContainer.call(menuContainer);
							}
						});

						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large','控制',start.firstChild,clickMode);
						node.link=page;
						node.type='cheat';
						page.classList.add('menu-sym');

						var currentrow1=null;
						var row1=ui.create.div('.menu-cheat',page);
						var clickrow1=function(){
							if(this.classList.contains('unselectable')) return;
							if(currentrow1==this){
								this.classList.remove('selectedx');
								currentrow1=null;
							}
							else{
								this.classList.add('selectedx');
								if(currentrow1){
									currentrow1.classList.remove('selectedx');
								}
								currentrow1=this;
								if(this.innerHTML=='换人'){
									for(var i=0;i<row3.childNodes.length;i++){
										row3.childNodes[i].classList.remove('glow');
									}
								}
							}
							checkCheat();
						};
						var nodedamage=ui.create.div('.menubutton','伤害',row1,clickrow1);
						var noderecover=ui.create.div('.menubutton','回复',row1,clickrow1);
						var nodedraw=ui.create.div('.menubutton','摸牌',row1,clickrow1);
						var nodediscard=ui.create.div('.menubutton','弃牌',row1,clickrow1);
						var nodelink=ui.create.div('.menubutton','横置',row1,clickrow1);
						var nodeturnover=ui.create.div('.menubutton','翻面',row1,clickrow1);
						var noderevive=ui.create.div('.menubutton','复活',row1,clickrow1);
						var nodereplace=ui.create.div('.menubutton','换人',row1,clickrow1);
						if(!game.canReplaceViewpoint||!game.canReplaceViewpoint()){
							nodereplace.classList.add('unselectable');
						}

						var currentrow2=null;
						var row2=ui.create.div('.menu-cheat',page);
						var clickrow2=function(){
							if(this.classList.contains('unselectable')) return;
							if(currentrow2==this){
								this.classList.remove('selectedx');
								currentrow2=null;
							}
							else{
								this.classList.add('selectedx');
								if(currentrow2){
									currentrow2.classList.remove('selectedx');
								}
								currentrow2=this;
							}
							checkCheat();
						};
						var nodex1=ui.create.div('.menubutton','一',row2,clickrow2);
						var nodex2=ui.create.div('.menubutton','二',row2,clickrow2);
						var nodex3=ui.create.div('.menubutton','三',row2,clickrow2);
						var nodex4=ui.create.div('.menubutton','四',row2,clickrow2);
						var nodex5=ui.create.div('.menubutton','五',row2,clickrow2);

						var row3=ui.create.div('.menu-buttons.leftbutton.commandbutton',page);
						row3.style.marginTop='3px';
						var clickrow3=function(){
							if(this.classList.contains('unselectable')) return;
							this.classList.toggle('glow');
							if(currentrow1&&currentrow1.innerHTML=='换人'&&this.classList.contains('glow')){
								if(this.link==game.me){
									this.classList.remove('glow');
								}
								for(var i=0;i<row3.childElementCount;i++){
									if(row3.childNodes[i]!=this){
										row3.childNodes[i].classList.remove('glow');
									}
								}
							}
							checkCheat();
						};
						menuUpdates.push(function(){
							if(_status.video||_status.connectMode){
								node.classList.add('off');
								if(node.classList.contains('active')){
									node.classList.remove('active');
									node.link.remove();
									active=start.firstChild.firstChild;
									active.classList.add('active');
									rightPane.appendChild(active.link);
								}

								page.remove();
								cheatButton.remove();
								if(_status.video) node.remove();
								return;
							}
							var list=[];
							for(var i=0;i<game.players.length;i++){
								if(lib.character[game.players[i].name]||game.players[i].name1){
									list.push(game.players[i]);
								}
							}
							for(var i=0;i<game.dead.length;i++){
								if(lib.character[game.dead[i].name]||game.dead[i].name1){
									list.push(game.dead[i]);
								}
							}
							if(list.length){
								row1.show();
								row2.show();
								row3.innerHTML='';
								var buttons=ui.create.buttons(list,'player',row3,true);
								for(var i=0;i<buttons.length;i++){
									buttons[i].listen(clickrow3);
									if(game.dead.contains(buttons[i].link)){
										buttons[i].dead=true;
									}
								}
								checkCheat();
							}
							else{
								row1.hide();
								row2.hide();
							}
							if(lib.config.mode=='identity'||lib.config.mode=='guozhan'||lib.config.mode=='doudizhu'){
								if(game.notMe||(game.me&&(game.me._trueMe||game.hasPlayer(function(current){
									return current._trueMe==game.me;
								})))||!game.phaseNumber||_status.qianlidanji){
									nodereplace.classList.add('unselectable');
								}
								else if(_status.event.isMine()&&ui.auto.classList.contains('hidden')){
									nodereplace.classList.add('unselectable');
								}
								else{
									nodereplace.classList.remove('unselectable');
								}
							}
							if(game.dead.length==0){
								noderevive.classList.add('unselectable');
							}
							else{
								noderevive.classList.remove('unselectable');
							}
							checkCheat();
						});
					}());
					(function(){
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large','命令',start.firstChild,clickMode);
						ui.commandnode=node;
						node.type='cmd';
						menuUpdates.push(function(){
							if(_status.connectMode){
								node.classList.add('off');
								if(node.classList.contains('active')){
									node.classList.remove('active');
									if(node.link) node.link.remove();
									active=start.firstChild.firstChild;
									active.classList.add('active');
									rightPane.appendChild(active.link);
								}
							}
						});
						node._initLink=function(){
							node.link=page;
							page.classList.add('menu-sym');
							var text=document.createElement('div');
							text.style.width='194px';
							text.style.height='124px';
							text.style.padding='3px';
							text.style.borderRadius='2px';
							text.style.boxShadow='rgba(0, 0, 0, 0.2) 0 0 0 1px';
							text.style.textAlign='left';
							text.style.webkitUserSelect='initial';
							text.style.overflow='scroll';
							text.style.position='absolute';
							text.style.left='30px';
							text.style.top='50px';
							text.style.wordBreak='break-all';
							var pre=ui.create.node('pre.fullsize',text);
							pre.style.margin=0;
							pre.style.padding=0;
							pre.style.position='relative';
							pre.style.webkitUserSelect = pre.style.userSelect = 'text';
							lib.setScroll(pre);
							page.appendChild(text);

							// var caption=ui.create.div('','输入命令',page);
							// caption.style.margin='6px';
							// caption.style.position='absolute';
							// caption.style.width='120px';
							// caption.style.top='129px';
							// caption.style.left='64px';
							var text2=document.createElement('input');
							text2.style.width='200px';
							text2.style.height='20px';
							text2.style.padding='0';
							text2.style.position='absolute';
							text2.style.top='15px';
							text2.style.left='30px';
							text2.style.resize='none';
							text2.style.border='none';
							text2.style.borderRadius='2px';
							text2.style.boxShadow='rgba(0, 0, 0, 0.2) 0 0 0 1px';
							var g={};
							var logs=[];
							var logindex=-1;
							var cheat=lib.cheat;
							//使用正则匹配绝大多数的普通obj对象,避免解析成代码块。
							var reg=/^\{([^{}]+:\s*([^\s,]*|'[^']*'|"[^"]*"|\{[^}]*\}|\[[^\]]*\]|null|undefined|([a-zA-Z$_][a-zA-Z0-9$_]*\s*:\s*)?[a-zA-Z$_][a-zA-Z0-9$_]*\(\)))(?:,\s*([^{}]+:\s*(?:[^\s,]*|'[^']*'|"[^"]*"|\{[^}]*\}|\[[^\]]*\]|null|undefined|([a-zA-Z$_][a-zA-Z0-9$_]*\s*:\s*)?[a-zA-Z$_][a-zA-Z0-9$_]*\(\))))*\}$/;
							//使用new Function隔绝作用域,避免在控制台可以直接访问到runCommand等变量
							var fun=(new Function('reg','value','_status','lib','game','ui','get','ai',`"use strict";\nreturn eval(reg.test(value)?('('+value+')'):value)`));
							var runCommand=function(e){
								if(text2.value&&!['up','down'].contains(text2.value)){
									logindex=-1;
									logs.unshift(text2.value);
								}
								if(text2.value=='cls'){
									pre.innerHTML='';
									text2.value='';
								}
								else if(text2.value=='up'){
									if(logindex+1<logs.length){
										text2.value=logs[++logindex];
									}
									else{
										text2.value='';
									}
								}
								else if(text2.value=='down'){
									if(logindex>=0){
										logindex--;
										if(logindex<0){
											text2.value='';
										}
										else{
											text2.value=logs[logindex];
										}
									}
									else{
										text2.value='';
									}
								}
								else if(text2.value.includes('无天使')&&(text2.value.includes('无神佛')||text2.value.includes('无神')&&text2.value.includes('无佛'))){
									game.print('密码正确!欢迎来到死后世界战线!');
									_status.keyVerified=true;
									text2.value='';
								}
								else{
									if(!game.observe&&!game.online){
										try{
											var value=text2.value.trim();
											if(value.endsWith(";")) value=value.slice(0,-1).trim();
											var result=fun(reg,value,_status,lib,game,ui,get,ai);
											game.print(result);
										}
										catch(e){
											game.print(e);
										}
									}
									text2.value='';
								}
							}
							text2.addEventListener('keydown',function(e){
								if(e.keyCode==13){
									runCommand();
								}
								else if(e.keyCode==38){
									if(logindex+1<logs.length){
										text2.value=logs[++logindex];
									}
								}
								else if(e.keyCode==40){
									if(logindex>=0){
										logindex--;
										if(logindex<0){
											text2.value='';
										}
										else{
											text2.value=logs[logindex];
										}
									}
								}
							});
							page.appendChild(text2);
							game.print=function(){
								var args=[].slice.call(arguments);
								var printResult=args.map(arg=>{
									if(get.is.object(arg)||typeof arg=='function'){
										var argi=get.stringify(arg);
										if(argi/*&&argi.length<5000*/){
											return argi.replace(/&/g, '&amp;')
												.replace(/</g, '&lt;')
												.replace(/>/g, '&gt;')
												.replace(/"/g, '&quot;')
												.replace(/'/g, '&#39;');
										}
										else return arg.toString();
									}else{
										var str=String(arg);
										if (!/<[a-zA-Z]+[^>]*?\/?>.*?(?=<\/[a-zA-Z]+[^>]*?>|$)/.exec(str)) return String(arg)
											.replace(/&/g, '&amp;')
											.replace(/</g, '&lt;')
											.replace(/>/g, '&gt;')
											.replace(/"/g, '&quot;')
											.replace(/'/g, '&#39;');
										else return str;
									}
								}).join(' ');
								pre.innerHTML+=printResult+'<br>';
								text.scrollTop=text.scrollHeight;
							}
							if(_status.toprint){
								for(var i=0;i<_status.toprint.length;i++){
									game.print.apply(this,_status.toprint[i]);
								}
								delete _status.toprint;
							}
							runButton.listen(runCommand);
							clearButton.listen(function(){
								pre.innerHTML='';
							});
						};
						if(!get.config('menu_loadondemand')) node._initLink();
					}());
					(function(){
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large','战绩',start.firstChild,clickMode);
						node.type='rec';
						node._initLink=function(){
							node.link=page;
							page.style.paddingBottom='10px';
							var reset=function(){
								if(this.innerHTML=='重置'){
									this.innerHTML='确定';
									var that=this;
									setTimeout(function(){
										that.innerHTML='重置';
									},1000);
								}
								else{
									this.parentNode.previousSibling.remove();
									this.parentNode.remove();
									lib.config.gameRecord[this.parentNode.link]={data:{}};
									game.saveConfig('gameRecord',lib.config.gameRecord);
								}
							}
							for(var i=0;i<lib.config.all.mode.length;i++){
								if(!lib.config.gameRecord[lib.config.all.mode[i]]) continue;
								if(lib.config.gameRecord[lib.config.all.mode[i]].str){
									ui.create.div('.config.indent',lib.translate[lib.config.all.mode[i]],page).style.marginBottom='-5px';
									var item=ui.create.div('.config.indent',lib.config.gameRecord[lib.config.all.mode[i]].str+'<span>重置</span>',page);
									item.style.height='auto';
									item.lastChild.addEventListener('click',reset);
									item.lastChild.classList.add('pointerdiv');
									item.link=lib.config.all.mode[i];
								}
							}
						};
						if(!get.config('menu_loadondemand')) node._initLink();
					}());
					(function(){
						if(!window.indexedDB||window.nodb) return;
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large','录像',start.firstChild,clickMode);
						node.type='video';
						lib.videos=[];
						ui.create.videoNode=(video,before)=>lib.videos[before===true?'unshift':'push'](video);
						node._initLink=function(){
							node.link=page;
							var store=lib.db.transaction(['video'],'readwrite').objectStore('video');
							store.openCursor().onsuccess=function(e){
								var cursor=e.target.result;
								if(cursor){
									lib.videos.push(cursor.value);
									cursor.continue();
								}
								else{
									lib.videos.sort(function(a,b){
										return parseInt(b.time)-parseInt(a.time);
									});
									var clickcapt=function(){
										var current=this.parentNode.querySelector('.videonode.active');
										if(current&&current!=this){
											current.classList.remove('active');
										}
										if(this.classList.toggle('active')){
											playButton.show();
											deleteButton.show();
											saveButton.show();
										}
										else{
											playButton.hide();
											deleteButton.hide();
											saveButton.hide();
										}
									};
									var staritem=function(){
										this.parentNode.classList.toggle('starred');
										var store=lib.db.transaction(['video'],'readwrite').objectStore('video');
										if(this.parentNode.classList.contains('starred')){
											this.parentNode.link.starred=true;
										}
										else{
											this.parentNode.link.starred=false;
										}
										store.put(this.parentNode.link);
									}
									var createNode=function(video,before){
										var node=ui.create.div('.videonode.menubutton.large',clickcapt);
										node.link=video;
										var nodename1=ui.create.div('.menubutton.videoavatar',node);
										nodename1.setBackground(video.name1,'character');
										if(video.name2){
											var nodename2=ui.create.div('.menubutton.videoavatar2',node);
											nodename2.setBackground(video.name2,'character');
										}
										var date=new Date(video.time);
										var str=date.getFullYear()+'.'+(date.getMonth()+1)+'.'+(date.getDate())+' '+
											date.getHours()+':';
										var minutes=date.getMinutes();
										if(minutes<10){
											str+='0';
										}
										str+=minutes;
										ui.create.div('.caption',video.name[0],node);
										ui.create.div('.text',str+'<br>'+video.name[1],node);
										if(video.win){
											ui.create.div('.victory','胜',node);
										}

										if(before){
											page.insertBefore(node,page.firstChild);
										}
										else{
											page.appendChild(node);
										}
										ui.create.div('.video_star','★',node,staritem);
										if(video.starred){
											node.classList.add('starred');
										}
									}
									for(var i=0;i<lib.videos.length;i++){
										createNode(lib.videos[i]);
									}
									ui.create.videoNode=createNode;
									var importVideoNode=ui.create.div('.config.switcher.pointerspan',
									'<span class="underlinenode slim ">导入录像...</span>',function(){
										this.nextSibling.classList.toggle('hidden');
									},page);
									importVideoNode.style.marginLeft='12px';
									importVideoNode.style.marginTop='3px';
									var importVideo=ui.create.div('.config.hidden',page);
									importVideo.style.whiteSpace='nowrap';
									importVideo.style.marginBottom='80px';
									importVideo.style.marginLeft='13px';
									importVideo.style.width='calc(100% - 30px)';
									importVideo.innerHTML='<input type="file" accept="*/*" style="width:calc(100% - 40px)">'+
									'<button style="width:40px">确定</button>';
									importVideo.lastChild.onclick=function(){
										var fileToLoad = importVideo.firstChild.files[0];
										var fileReader = new FileReader();
										fileReader.onload = function(fileLoadedEvent)
										{
											var data = fileLoadedEvent.target.result;
											if(!data) return;
											try{
												data=JSON.parse(lib.init.decode(data));
											}
											catch(e){
												console.log(e);
												alert('导入失败');
												return;
											}
											var store=lib.db.transaction(['video'],'readwrite').objectStore('video');
											var videos=lib.videos.slice(0);
											for(var i=0;i<videos.length;i++){
												if(videos[i].starred){
													videos.splice(i--,1);
												}
											}
											for(var deletei=0;deletei<5;deletei++){
												if(videos.length>=parseInt(lib.config.video)&&videos.length){
													var toremove=videos.pop();
													lib.videos.remove(toremove);
													store.delete(toremove.time);
													for(var i=0;i<page.childNodes.length;i++){
														if(page.childNodes[i].link==toremove){
															page.childNodes[i].remove();
															break;
														}
													}
												}
												else{
													break;
												}
											}
											for(var i=0;i<lib.videos.length;i++){
												if(lib.videos[i].time==data.time){
													alert('录像已存在');
													return;
												}
											}
											lib.videos.unshift(data);
											store.put(data);
											createNode(data,true);
										};
										fileReader.readAsText(fileToLoad, "UTF-8");
									}

									playButton.listen(function(){
										var current=this.parentNode.querySelector('.videonode.active');
										if(current){
											game.playVideo(current.link.time,current.link.mode);
										}
									});
									deleteButton.listen(function(){
										var current=this.parentNode.querySelector('.videonode.active');
										if(current){
											lib.videos.remove(current.link);
											var store=lib.db.transaction(['video'],'readwrite').objectStore('video');
											store.delete(current.link.time);
											current.remove();
										}
									});
									saveButton.listen(function(){
										var current=this.parentNode.querySelector('.videonode.active');
										if(current){
											game.export(lib.init.encode(JSON.stringify(current.link)),
											'无名杀 - 录像 - '+current.link.name[0]+' - '+current.link.name[1]);
										}
									});

									ui.updateVideoMenu=function(){
										var active=start.firstChild.querySelector('.active');
										if(active){
											active.classList.remove('active');
											active.link.remove();
										}
										node.classList.add('active');
										rightPane.appendChild(page);
										playButton.style.display='';
										deleteButton.style.display='';
										saveButton.style.display='';
									}
								}
							};
						};
						if(!get.config('menu_loadondemand')) node._initLink();
					}());


					for(var i in lib.help){
						var page=ui.create.div('');
						var node=ui.create.div('.menubutton.large',i,start.firstChild,clickMode);
						node.type='help';
						node.link=page;
						node.style.display='none';
						page.classList.add('menu-help');
						page.innerHTML=lib.help[i];
					}

					if(!connectMenu){
						var node=ui.create.div('.menubutton.large','帮助',start.firstChild,function(){
							var activex=start.firstChild.querySelector('.active');
							if(this.innerHTML=='帮助'){
								cheatButton.style.display='none';
								runButton.style.display='none';
								clearButton.style.display='none';
								playButton.style.display='none';
								saveButton.style.display='none';
								deleteButton.style.display='none';

								this.innerHTML='返回';
								for(var i=0;i<start.firstChild.childElementCount;i++){
									var nodex=start.firstChild.childNodes[i];
									if(nodex==node) continue;
									if(nodex.type=='help'){
										nodex.style.display='';
										if(activex&&activex.type!='help'){
											activex.classList.remove('active');
											activex.link.remove();
											activex=null;
											nodex.classList.add('active');
											rightPane.appendChild(nodex.link);
										}
									}
									else{
										nodex.style.display='none';
									}
								}
							}
							else{
								this.innerHTML='帮助';
								for(var i=0;i<start.firstChild.childElementCount;i++){
									var nodex=start.firstChild.childNodes[i];
									if(nodex==node) continue;
									if(nodex.type!='help'){
										nodex.style.display='';
										if(activex&&activex.type=='help'){
											activex.classList.remove('active');
											activex.link.remove();
											activex=null;
											clickMode.call(nodex);
										}
									}
									else{
										nodex.style.display='none';
									}
								}
							}
						});
					}

					var active=start.firstChild.querySelector('.active');
					if(!active){
						active=start.firstChild.firstChild;
						active.classList.add('active');
					}
					if(!active.link) active._initLink();
					rightPane.appendChild(active.link);
				}());

				if(menuTimeout){
					clearTimeout(menuTimeout);
					delete window.resetExtension;
					localStorage.removeItem(lib.configprefix+'disable_extension',true);
				}
			},
			table:function(){
				var str,row,col,position,position2,fixed,style,divposition;
				for(var i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='string') str=arguments[i];
					else if(typeof arguments[i]=='number'){
						if(typeof row=='number'){
							if(typeof col=='number') position2=arguments[i];
							else col=arguments[i];
						}
						else row=arguments[i];
					}
					else if(get.objtype(arguments[i])=='div'||
						get.objtype(arguments[i])=='table'||
						get.objtype(arguments[i])=='tr'||
						get.objtype(arguments[i])=='td'||
						get.objtype(arguments[i])=='body') position=arguments[i];
					else if(typeof arguments[i]=='boolean') fixed=arguments[i];
					else if(get.itemtype(arguments[i])=='divposition') divposition=arguments[i];
					else if(typeof arguments[i]=='object') style=arguments[i];
				}
				if(str==undefined) str='';
				var node=document.createElement('table');
				for(var i=0;i<str.length;i++){
					if(str[i]=='.'){
						if(node.className.length!=0){
							node.className+=' ';
						}
						while(str[i+1]!='.'&&str[i+1]!='#'&&i+1<str.length){
							node.className+=str[i+1];
							i++;
						}
					}
					else if(str[i]=='#'){
						while(str[i+1]!='.'&&str[i+1]!='#'&&i+1<str.length){
							node.id+=str[i+1];
							i++;
						}
					}
				}
				var tr,td;
				for(var i=0;i<row;i++){
					tr=document.createElement('tr');
					if(fixed) tr.style.height=(100/row)+'%';
					node.appendChild(tr);
					for(var j=0;j<col;j++){
						td=document.createElement('td');
						tr.appendChild(td);
					}
				}
				if(position){
					if(typeof position2=='number'&&position.childNodes.length>position2){
						position.insertBefore(node,position.childNodes[position2]);
					}
					else{
						position.appendChild(node);
					}
				}
				return node;
			},
			giveup:function(){
				if(ui.giveup) return;
				if(!lib.config.show_giveup) return;
				ui.giveup=ui.create.system('投降',function(){
					var player=game.me;
					this.remove();
					if(game.online){
						game.send('giveup',player);
					}
					else{
						_status.event.next.length=0;
						game.createEvent('giveup',false).set('includeOut',true).setContent(function(){
							game.log(player,'投降');
							player.popup('投降');
							player.die('nosource').includeOut=true;
						}).player=player;
					}
					if(_status.paused&&_status.imchoosing&&!_status.auto){
						ui.click.auto();
					}
				},true,true);
			},
			groupControl:function(dialog){
				return ui.create.control('wei','shu','wu','qun','jin','western','key',function(link,node){
					if(link=='全部'){
						dialog.currentcapt='';
						dialog.currentgroup='';
						for(var i=0;i<dialog.buttons.length;i++){
							dialog.buttons[i].style.display='';
						}
					}
					else{
						if(node.classList.contains('thundertext')){
							dialog.currentgroup=null;
							dialog.currentgroupnode=null;
							node.classList.remove('thundertext');
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.currentcapt&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
						else{
							if(dialog.currentgroupnode){
								dialog.currentgroupnode.classList.remove('thundertext');
							}
							dialog.currentgroup=link;
							dialog.currentgroupnode=node;
							node.classList.add('thundertext');
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.buttons[i].group!=link||
								(dialog.currentcapt&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt))){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
					}
				});
			},
			cardDialog:function(){
				var args=['thisiscard'];
				for(var i=0;i<arguments.length;i++){
					args.push(arguments[i]);
				}
				return ui.create.characterDialog.apply(this,args);
			},
			characterDialog2:function(filter){
				var list=[];
				for(var i in lib.character){
					if(lib.character[i][4].contains('minskin')) continue;
					if(lib.character[i][4].contains('boss')||lib.character[i][4].contains('hiddenboss')){
						if(lib.config.mode=='boss') continue;
						if(!lib.character[i][4].contains('bossallowed')) continue;
					}

					if(lib.character[i][4].contains('stonehidden')) continue;
					if(lib.config.banned.contains(i)) continue;
					if(filter&&filter(i)) continue;
					list.push(i);
				}
				var dialog=ui.create.dialog('hidden');
				dialog.classList.add('noupdate');
				dialog.classList.add('scroll1');
				dialog.classList.add('scroll2');
				dialog.classList.add('scroll3');
				list.sort(lib.sort.character);
				dialog.classList.add('character');
				dialog.classList.add('choose-character');
				var getPack=function(name){
					for(var i in lib.characterPack){
						if(lib.characterPack[i][name]) return i;
					}
					return null;
				}
				var packs={};
				var packnode=ui.create.div('.packnode',dialog);
				lib.setScroll(packnode);
				var clickCapt=function(){
					var active=this.parentNode.querySelector('.active');
					if(active){
						active.classList.remove('active');
					}
					this.classList.add('active');
					for(var i=0;i<dialog.buttons.length;i++){
						if(this.pack&&!this.pack.contains(dialog.buttons[i].link)){
							dialog.buttons[i].classList.add('nodisplay');
						}
						else{
							dialog.buttons[i].classList.remove('nodisplay');
						}
					}
				}
				var createNode=function(packname){
					var translate;
					var pack=null;
					if(packname=='最近'){
						pack=get.config('recentCharacter')||[];
					}
					else if(packname=='收藏'){
						pack=lib.config.favouriteCharacter;
					}
					var node=ui.create.div('.dialogbutton.menubutton.large',packname,packnode,clickCapt);
					node.pack=pack;
					return node;
				}
				dialog.add([list,'character']);
				var bool=true;
				var node;
				var recent=get.config('recentCharacter');
				if(recent&&recent.length){
					node=createNode('最近');
					if(lib.config.character_dialog_tool=='最近'){
						clickCapt.call(node);
						bool=false;
					}
				}
				if(lib.config.favouriteCharacter.length){
					node=createNode('收藏');
					if(lib.config.character_dialog_tool=='收藏'){
						clickCapt.call(node);
						bool=false;
					}
				}
				var node=createNode('全部');
				if(lib.config.character_dialog_tool=='all'){
					clickCapt.call(node);
					bool=false;
				}
				if(bool){
					clickCapt.call(packnode.firstChild);
				}

				var node=ui.create.div('.dialogbutton.menubutton.large','筛选',packnode);
				return dialog;
			},
			characterDialog:function(){
				// if(lib.config.character_dialog_style=='newstyle'){
				//     for(var i=0;i<arguments.length;i++){
				//      			if(arguments[i]=='thisiscard'){
				//      						 break;
				//      			}
				//     }
				//     if(i==arguments.length){
				//      			return ui.create.characterDialog2.apply(this,arguments);
				//     }
				// }
				var filter,str,noclick,thisiscard,seperate,expandall,onlypack,heightset,precharacter,characterx;
				for(var i=0;i<arguments.length;i++){
					if(arguments[i]==='thisiscard'){
						thisiscard=true;
					}
					else if(arguments[i]==='expandall'){
						expandall=true;
					}
					else if(arguments[i]==='heightset'){
						heightset=true;
					}
					else if(arguments[i]=='precharacter'){
						precharacter=true;
					}
					else if(arguments[i]=='characterx'){
						characterx=true;
					}
					else if(typeof arguments[i]=='string'&&arguments[i].startsWith('onlypack:')){
						onlypack=arguments[i].slice(9);
					}
					else if(typeof arguments[i]=='object'&&typeof arguments[i].seperate=='function'){
						seperate=arguments[i].seperate;
					}
					else if(typeof arguments[i]==='string'){
						str=arguments[i];
					}
					else if(typeof arguments[i]==='function'){
						filter=arguments[i];
					}
					else if(typeof arguments[i]=='boolean'){
						noclick=arguments[i];
					}
				}
				var list=[];
				const groups=[];
				var dialog;
				var node=ui.create.div('.caption.pointerspan');
				if(get.is.phoneLayout()){
					node.style.fontSize='30px';
				}
				var namecapt=[];
				var getCapt=function(str){
					var capt;
					if(str.indexOf('_')==-1){
						capt=str[0];
					}
					else{
						capt=str[str.lastIndexOf('_')+1];
					}
					capt=capt.toLowerCase();
					if(!/[a-z]/i.test(capt)){
						capt='自定义';
					}
					return capt;
				}
				if(thisiscard){
					for(var i in lib.card){
						if(!lib.translate[i+'_info']) continue;
						if(filter&&filter(i)) continue;
						list.push(['',get.translation(lib.card[i].type),i]);
						if(namecapt.indexOf(getCapt(i))==-1){
							namecapt.push(getCapt(i));
						}
					}
				}
				else{
					for(var i in lib.character){
						if(lib.character[i][4].contains('minskin')) continue;
						if(lib.character[i][4].contains('boss')||lib.character[i][4].contains('hiddenboss')){
							if(lib.config.mode=='boss') continue;
							if(!lib.character[i][4].contains('bossallowed')) continue;
						}

						if(lib.character[i][4].contains('stonehidden')) continue;
						if(lib.character[i][4].contains('unseen')) continue;
						if(lib.config.banned.contains(i)) continue;
						if(lib.characterFilter[i]&&!lib.characterFilter[i](get.mode())) continue;
						if(filter&&filter(i)) continue;
						list.push(i);
						if(get.is.double(i)){
							groups.add('double');
						}
						else groups.add(lib.character[i][1]);
						if(namecapt.indexOf(getCapt(i))==-1){
							namecapt.push(getCapt(i));
						}
					}
				}
				namecapt.sort(function(a,b){
					return a>b?1:-1;
				});
				groups.sort(lib.sort.group);
				if(!thisiscard){
					namecapt.remove('自定义');
					namecapt.push('newline');
					for(var i in lib.characterDialogGroup){
						namecapt.push(i);
					}
				}
				var newlined=false;
				var newlined2;
				var packsource;
				var clickCapt=function(e){
					if(_status.dragged) return;
					if(dialog.currentcapt2=='最近'&&dialog.currentcaptnode2!=this&&!dialog.currentcaptnode2.inited){
						dialog.currentcapt2=null;
						dialog.currentcaptnode2.classList.remove('thundertext');
						dialog.currentcaptnode2.inited=true;
						dialog.currentcaptnode2=null;
					}
					if(this.alphabet){
						if(this.classList.contains('thundertext')){
							dialog.currentcapt=null;
							dialog.currentcaptnode=null;
							this.classList.remove('thundertext');
							if(this.touchlink){
								this.touchlink.classList.remove('active');
							}
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.currentgroup&&dialog.buttons[i].group!=dialog.currentgroup){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentcapt2&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt,true)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
						else{
							if(dialog.currentcaptnode){
								dialog.currentcaptnode.classList.remove('thundertext');
								if(dialog.currentcaptnode.touchlink){
									dialog.currentcaptnode.touchlink.classList.remove('active');
								}
							}
							dialog.currentcapt=this.link;
							dialog.currentcaptnode=this;
							this.classList.add('thundertext');
							if(this.touchlink){
								this.touchlink.classList.add('active');
							}
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentcapt2&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt,true)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentgroup&&dialog.buttons[i].group!=dialog.currentgroup){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
					}
					else{
						if(newlined2){
							newlined2.style.display='none';
							if(!packsource.onlypack){
								packsource.classList.remove('thundertext');
								if(!get.is.phoneLayout()||!lib.config.filternode_button){
									packsource.innerHTML='武将包';
								}
							}
						}
						if(this.classList.contains('thundertext')){
							dialog.currentcapt2=null;
							dialog.currentcaptnode2=null;
							this.classList.remove('thundertext');
							if(this.touchlink){
								this.touchlink.classList.remove('active');
							}
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.currentgroup&&dialog.buttons[i].group!=dialog.currentgroup){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentcapt&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
						else{
							if(dialog.currentcaptnode2){
								dialog.currentcaptnode2.classList.remove('thundertext');
								if(dialog.currentcaptnode2.touchlink){
									dialog.currentcaptnode2.touchlink.classList.remove('active');
								}
							}
							dialog.currentcapt2=this.link;
							dialog.currentcaptnode2=this;
							this.classList.add('thundertext');
							if(this.touchlink){
								this.touchlink.classList.add('active');
							}
							else if(this.parentNode==newlined2){
								packsource.innerHTML=this.innerHTML;
								packsource.classList.add('thundertext');
							}
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.currentcapt&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt,true)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentgroup&&dialog.buttons[i].group!=dialog.currentgroup){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									if(dialog.buttons[i].activate){
										dialog.buttons[i].activate();
									}
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
					}
					if(dialog.seperate){
						for(var i=0;i<dialog.seperate.length;i++){
							if(!dialog.seperate[i].nextSibling.querySelector('.button:not(.nodisplay)')){
								dialog.seperate[i].style.display='none';
								dialog.seperate[i].nextSibling.style.display='none';
							}
							else{
								dialog.seperate[i].style.display='';
								dialog.seperate[i].nextSibling.style.display='';
							}
						}
					}
					if(filternode){
						if(filternode.querySelector('.active')){
							packsource.classList.add('thundertext');
						}
						else{
							packsource.classList.remove('thundertext');
						}
					}
					if(e) e.stopPropagation();
				};
				for(i=0;i<namecapt.length;i++){
					if(namecapt[i]=='newline'){
						newlined=document.createElement('div');
						newlined.style.marginTop='5px';
						newlined.style.display='block';
						// newlined.style.fontFamily='xinwei';
						if(get.is.phoneLayout()){
							newlined.style.fontSize='32px';
						}
						else{
							newlined.style.fontSize='22px';
						}
						newlined.style.textAlign='center';
						node.appendChild(newlined);
					}
					else if(newlined){
						var span=ui.create.div('.tdnode.pointerdiv.shadowed.reduce_radius');
						span.style.margin='3px';
						span.style.width='auto';
						span.innerHTML=' '+namecapt[i].toUpperCase()+' ';
						span.link=namecapt[i];
						span.addEventListener(lib.config.touchscreen?'touchend':'click',clickCapt);
						newlined.appendChild(span);
						node[namecapt[i]]=span;
						if(namecapt[i]=='收藏'){
							span._nature='fire';
						}
						else{
							span._nature='wood';
						}
					}
					else{
						var span=document.createElement('span');
						span.innerHTML=' '+namecapt[i].toUpperCase()+' ';
						span.link=namecapt[i];
						span.alphabet=true;
						span.addEventListener(lib.config.touchscreen?'touchend':'click',clickCapt);
						node.appendChild(span);
					}
				}
				if(!thisiscard){
					var natures=['water','soil','wood','metal'];
					var span=document.createElement('span');
					newlined.appendChild(span);
					span.style.margin='8px';
					var clickGroup=function(){
						if(_status.dragged) return;
						if(dialog.currentcapt2=='最近'&&dialog.currentcaptnode2!=this&&!dialog.currentcaptnode2.inited){
							dialog.currentcapt2=null;
							dialog.currentcaptnode2.classList.remove('thundertext');
							dialog.currentcaptnode2.inited=true;
							dialog.currentcaptnode2=null;
						}
						var node=this,link=this.link;
						if(node.classList.contains('thundertext')){
							dialog.currentgroup=null;
							dialog.currentgroupnode=null;
							node.classList.remove('thundertext');
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.currentcapt&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentcapt2&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt,true)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									dialog.buttons[i].classList.remove('nodisplay');
								}
							}
						}
						else{
							if(dialog.currentgroupnode){
								dialog.currentgroupnode.classList.remove('thundertext');
							}
							dialog.currentgroup=link;
							dialog.currentgroupnode=node;
							node.classList.add('thundertext');
							for(var i=0;i<dialog.buttons.length;i++){
								if(dialog.currentcapt&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentcapt2&&dialog.buttons[i].capt!=dialog.getCurrentCapt(dialog.buttons[i].link,dialog.buttons[i].capt,true)){
									dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentgroup=='double'){
									if(dialog.buttons[i]._changeGroup) dialog.buttons[i].classList.remove('nodisplay');
									else dialog.buttons[i].classList.add('nodisplay');
								}
								else if(dialog.currentgroup=='ye'){
									if(dialog.buttons[i].group=='ye') dialog.buttons[i].classList.remove('nodisplay');
									else dialog.buttons[i].classList.add('nodisplay');
								}
								else{
									if(dialog.buttons[i]._changeGroup||dialog.buttons[i].group!=dialog.currentgroup){
										dialog.buttons[i].classList.add('nodisplay');
									}
									else{
										dialog.buttons[i].classList.remove('nodisplay');
									}
								}
							}
						}
					};
					for(var i=0;i<groups.length;i++){
						var span=ui.create.div('.tdnode.pointerdiv.shadowed.reduce_radius.reduce_margin');
						span.style.margin='3px';
						newlined.appendChild(span);
						span.innerHTML=get.translation(groups[i]);
						span.link=groups[i];
						span._nature=natures[i];
						span.addEventListener(lib.config.touchscreen?'touchend':'click',clickGroup);
					}

					var span=document.createElement('span');
					newlined.appendChild(span);
					span.style.margin='8px';

					packsource=ui.create.div('.tdnode.pointerdiv.shadowed.reduce_radius.reduce_margin');
					packsource.style.margin='3px';
					newlined.appendChild(packsource);
					var filternode=null;
					var clickCaptNode=function(e){
						delete _status.filterCharacter;
						ui.window.classList.remove('shortcutpaused');
						filternode.delete();
						filternode.classList.remove('shown');
						clickCapt.call(this.link,e);
					};
					if(get.is.phoneLayout()&&lib.config.filternode_button){
						newlined.style.marginTop='';
						packsource.innerHTML='筛选';
						filternode=ui.create.div('.popup-container.filter-character.modenopause');
						ui.create.div(filternode);
						filternode.listen(function(e){
							if(this.classList.contains('removing')) return;
							delete _status.filterCharacter;
							ui.window.classList.remove('shortcutpaused');
							this.delete();
							this.classList.remove('shown');
							e.stopPropagation();
						});
						for(var i=0;i<node.childElementCount;i++){
							if(node.childNodes[i].tagName.toLowerCase()=='span'){
								node.childNodes[i].style.display='none';
								node.childNodes[i].touchlink=ui.create.div(filternode.firstChild,clickCaptNode,'.menubutton.large.capt',node.childNodes[i].innerHTML);
								node.childNodes[i].touchlink.link=node.childNodes[i];
							}
						}
						ui.create.node('br',filternode.firstChild);
					}
					else{
						if(onlypack){
							packsource.onlypack=true;
							packsource.innerHTML=get.translation(onlypack+'_character_config');
							packsource.style.display='none';
							packsource.previousSibling.style.display='none';
						}
						else{
							packsource.innerHTML='武将包';
						}
					}

					newlined2=document.createElement('div');
					newlined2.style.marginTop='5px';
					newlined2.style.display='none';
					newlined2.style.fontFamily='xinwei';
					newlined2.classList.add('pointernode');
					if(get.is.phoneLayout()){
						newlined2.style.fontSize='32px';
					}
					else{
						newlined2.style.fontSize='22px';
					}
					newlined2.style.textAlign='center';
					node.appendChild(newlined2);

					packsource.addEventListener(lib.config.touchscreen?'touchend':'click',function(){
						if(packsource.onlypack) return;
						if(_status.dragged) return;
						if(get.is.phoneLayout()&&lib.config.filternode_button&&filternode){
							_status.filterCharacter=true;
							ui.window.classList.add('shortcutpaused');
							ui.window.appendChild(filternode);
							ui.refresh(filternode);
							filternode.classList.add('shown');
							var dh=filternode.offsetHeight-filternode.firstChild.offsetHeight;
							if(dh>0){
								filternode.firstChild.style.top=(dh/2)+'px';
							}
							else{
								filternode.firstChild.style.top='';
							}
						}
						else{
							if(newlined2.style.display=='none'){
								newlined2.style.display='block';
							}
							else{
								newlined2.style.display='none';
							}
						}
					});
					var packlist=[];
					for(var i=0;i<lib.config.all.characters.length;i++){
						if(!lib.config.characters.contains(lib.config.all.characters[i])) continue;
						packlist.push(lib.config.all.characters[i]);
					}
					for(var i in lib.characterPack){
						if(!lib.config.all.characters.contains(i)){
							packlist.push(i);
						}
					}
					for(var i=0;i<packlist.length;i++){
						var span=document.createElement('div');
						span.style.display='inline-block';
						span.style.width='auto';
						span.style.margin='5px';
						if(get.is.phoneLayout()){
							span.style.fontSize='32px';
						}
						else{
							span.style.fontSize='22px';
						}
						span.innerHTML=lib.translate[packlist[i]+'_character_config'];
						span.link=packlist[i];
						span.addEventListener(lib.config.touchscreen?'touchend':'click',clickCapt);
						newlined2.appendChild(span);
						if(filternode&&!onlypack){
							span.touchlink=ui.create.div(filternode.firstChild,clickCaptNode,'.menubutton.large',span.innerHTML);
							span.touchlink.link=span;
						}
					}
				}

				var groupSort;
				if(thisiscard){
					groupSort=function(name){
						var type=lib.card[name[2]].type;
						if(lib.cardType[type]){
							return lib.cardType[type];
						}
						switch(type){
							case 'basic':return 0;
							case 'chess':return 1.5;
							case 'trick':return 2;
							case 'delay':return 3;
							case 'equip':return 4;
							case 'zhenfa':return 5;
							default:return 6;
						}
					}
					list.sort(function(a,b){
						var del=groupSort(a)-groupSort(b);
						if(del!=0) return del;
						var aa=a,bb=b;
						if(a.includes('_')){
							a=a.slice(a.lastIndexOf('_')+1);
						}
						if(b.includes('_')){
							b=b.slice(b.lastIndexOf('_')+1);
						}
						if(a!=b){
							return a>b?1:-1;
						}
						return aa>bb?1:-1;
					});
				}
				else{
					list.sort(lib.sort.character);
				}
				dialog=ui.create.dialog('hidden');
				dialog.classList.add('noupdate');
				dialog.classList.add('scroll1');
				dialog.classList.add('scroll2');
				dialog.classList.add('scroll3');
				dialog.addEventListener(lib.config.touchscreen?'touchend':'mouseup',function(){
					_status.clicked2=true;
				});
				if(heightset){
					dialog.style.height=((game.layout=='long2'||game.layout=='nova')?380:350)+'px';
					dialog._scrollset=true;
				}
				dialog.getCurrentCapt=function(link,capt,noalph){
					var currentcapt=noalph?this.currentcapt2:this.currentcapt;
					if(this.seperatelist&&noalph){
						if(this.seperatelist[currentcapt].contains(link)) return capt;
						return null;
					}
					if(lib.characterDialogGroup[currentcapt]){
						return lib.characterDialogGroup[currentcapt](link,capt);
					}
					if(lib.characterPack[currentcapt]){
						if(lib.characterPack[currentcapt][link]){
							return capt;
						}
						return null;
					}
					return this.currentcapt;
				}
				if(str){
					dialog.add(str);
				}
				dialog.add(node);
				if(thisiscard){
					if(seperate){
						seperate=seperate(list);
						dialog.seperate=[];
						dialog.seperatelist=seperate.list;
						if(dialog.seperatelist){
							newlined=document.createElement('div');
							newlined.style.marginTop='5px';
							newlined.style.display='block';
							newlined.style.fontFamily='xinwei';
							if(get.is.phoneLayout()){
								newlined.style.fontSize='32px';
							}
							else{
								newlined.style.fontSize='22px';
							}
							newlined.style.textAlign='center';
							node.appendChild(newlined);
							for(var i in dialog.seperatelist){
								var span=document.createElement('span');
								span.style.margin='3px';
								span.innerHTML=i;
								span.link=i;
								span.seperate=true;
								span.addEventListener(lib.config.touchscreen?'touchend':'click',clickCapt);
								newlined.appendChild(span);
							}
						}
						for(var i in seperate){
							if(i=='list') continue;
							var link='';
							var linkcontent=seperate[i];
							if(i.includes('_link:')){
								link=i.slice(i.indexOf('_link:')+6);
								i=i.slice(0,i.indexOf('_link:'));
							}
							var nodesep=dialog.add(i);
							nodesep.link=link;
							dialog.seperate.push(nodesep);
							dialog.add([linkcontent,'vcard'],noclick);
						}
					}
					else{
						dialog.add([list,'vcard'],noclick);
					}
				}
				else{
					if(precharacter){
						dialog.add([list,'precharacter'],noclick);
					}
					else if(characterx){
						dialog.add([list,'characterx'],noclick);
					}
					else{
						dialog.add([list,'character'],noclick);
					}
				}
				dialog.add(ui.create.div('.placeholder'));
				for(i=0;i<dialog.buttons.length;i++){
					if(thisiscard){
						dialog.buttons[i].capt=getCapt(dialog.buttons[i].link[2]);
					}
					else{
						dialog.buttons[i].group=lib.character[dialog.buttons[i].link][1];
						dialog.buttons[i].capt=getCapt(dialog.buttons[i].link);
					}
				}
				if(!expandall){
					if(!thisiscard&&(lib.characterDialogGroup[lib.config.character_dialog_tool]||
						lib.config.character_dialog_tool=='自创')){
						clickCapt.call(node[lib.config.character_dialog_tool]);
					}
				}
				return dialog;
			},
			dialog:function(){
				var i;
				var hidden=false;
				var notouchscroll=false;
				var forcebutton=false;
				var noforcebutton=false;
				var dialog=ui.create.div('.dialog');
				dialog.contentContainer=ui.create.div('.content-container',dialog);
				dialog.content=ui.create.div('.content',dialog.contentContainer);
				dialog.bar1=ui.create.div('.bar.top',dialog);
				dialog.bar2=ui.create.div('.bar.bottom',dialog);
				dialog.buttons=[];
				for(i in lib.element.dialog){
					dialog[i]=lib.element.dialog[i];
				}
				for(i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='boolean') dialog.static=arguments[i];
					else if(arguments[i]=='hidden') hidden=true;
					else if(arguments[i]=='notouchscroll') notouchscroll=true;
					else if(arguments[i]=='forcebutton') forcebutton=true;
					else if(arguments[i]=='noforcebutton') noforcebutton=true;
					else dialog.add(arguments[i]);
				}
				if(!hidden){
					dialog.open();
				}
				if(!lib.config.touchscreen) dialog.contentContainer.onscroll=ui.update;
				if(!notouchscroll){
					dialog.contentContainer.ontouchstart=ui.click.dialogtouchStart;
					dialog.contentContainer.ontouchmove = ui.click.touchScroll;
					dialog.contentContainer.style.WebkitOverflowScrolling='touch';
					dialog.ontouchstart=ui.click.dragtouchdialog;
				}
				if(noforcebutton){
					dialog.noforcebutton=true;
				}
				else if(forcebutton){
					dialog.forcebutton=true;
					dialog.classList.add('forcebutton');
				}
				return dialog;
			},
			line2:function(){
				var node=ui.create.line.apply(this,arguments);
				node.classList.add('line2');
				return node;
			},
			line:function(){
				var two=false,func;
				var node=ui.create.div('.config');
				for(var i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='string'||typeof arguments[i]=='number'){
						if(two) ui.create.div('.toggle',node).innerHTML=arguments[i];
						else {
							ui.create.div(node).innerHTML=arguments[i];
							two=true;
						}
					}
					else if(typeof arguments[i]=='function') func=arguments[i];
				}
				if(func){
					for(var i=0;i<node.childNodes.length;i++) node.childNodes[i].listen(func);
				}
				return node;
			},
			switcher:function(name,current,current2){
				var func;
				var node=ui.create.div('.config');
				ui.create.div(node).innerHTML=get.translation(name+'_config');
				var switcher=ui.create.div('.toggle.pointerdiv',node);
				switcher.name=name;
				for(var i=0;i<arguments.length;i++){
					if(typeof arguments[i]=='function'){
						func=arguments[i];break;
					}
				}
				if(typeof current=='string'){
					switcher.link=current;
					switcher.innerHTML=get.translation(current);
					switcher.contentEditable=true;
					switcher.style.webkitUserSelect='text';
					switcher.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.editor);
				}
				else if(typeof current=='object'){
					switcher.link=current2||current[0];
					switcher.innerHTML=get.translation(switcher.link);
					switcher.choice=current;
					switcher.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.switcher);
				}
				else{
					if(current){
						switcher.classList.add('on');
					}
					switcher.classList.add('onoff');
					ui.create.div(ui.create.div(switcher));
					switcher.link=current?true:false;
					switcher.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.toggle);
				}
				if(func) switcher.additionalCommand=func;
				return node;
			},
			caption:function(str,position){
				var caption=ui.create.div('.caption',position);
				caption.innerHTML=str;
				return caption;
			},
			control:function(){
				var nc=!ui.control.querySelector('div:not(.removing):not(.stayleft)');
				// for(var i=0;i<ui.control.childNodes.length;i++){
				// 	if(ui.control.childNodes[i].classList.contains('removing')){
				// 		var that=ui.control.childNodes[i];
				// 		var width=that.offsetWidth;
				// 		that.style.marginLeft=(-width/2)+'px';
				// 		that.style.marginRight=(-width/2)+'px';
				// 		that.style.transitionDuration=0.8*parseFloat(getComputedStyle(that).opacity)+'s';
				// 	}
				// }
				var i,controls;
				var nozoom=false;
				if(Array.isArray(arguments[0])) controls=arguments[0];
				else controls=arguments;
				var control=ui.create.div('.control');
				ui.control.insertBefore(control,_status.createControl||ui.confirm);
				for(i in lib.element.control){
					control[i]=lib.element.control[i];
				}
				for(i=0;i<controls.length;i++){
					if(typeof controls[i]=='function'){
						control.custom=controls[i];
					}
					else if(controls[i]=='nozoom'){
						nozoom=true;
					}
					else if(controls[i]=='stayleft'){
						control.stayleft=true;
						control.classList.add('stayleft');
					}
					else{
						control.add(controls[i]);
					}
				}
				ui.controls.unshift(control);
				if(nc){
					ui.control.animate('nozoom',100);
				}
				// if(ui.control.classList.contains('nozoom')){
				// 	nozoom=true;
				// }
				// if(nozoom){
				// 	control.classList.add('nozoom');
				// }
				if(control.childNodes.length){
					// if(nozoom||true){
					control.style.transition='opacity 0.5s';
					control.animate('controlpressdownx',500);
					// }
					// else{
					// 	control.style.transition='';
					// 	control.style.transform='scale(0.8)';
					// }
					ui.refresh(control);
					if(!control.stayleft){
						control.style.transform='translateX(-'+(control.offsetWidth/2)+'px)';
					}
					control.style.opacity=1;
					ui.refresh(control);
					control.style.transition='';
				}

				control.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.control2);

				if(lib.config.button_press){
					control.addEventListener(lib.config.touchscreen?'touchstart':'mousedown',function(){
						if(this.classList.contains('disabled')) return;
						this.classList.add('controlpressdown');
						if(typeof this._offset=='number'){
							this.style.transform='translateX('+this._offset+'px) scale(0.97)';
						}
					});
					control.addEventListener(lib.config.touchscreen?'touchend':'mouseup',function(){
						this.classList.remove('controlpressdown');
						if(typeof this._offset=='number'){
							this.style.transform='translateX('+this._offset+'px)';
						}
					});
				}

				ui.updatec();
				return control;
			},
			confirm:function(str,func){
				if(ui.confirm&&ui.confirm.str==str){
					return;
				}
				if(str=='o'){
					if(ui.confirm){
						ui.confirm.replace('ok');
					}
					else{
						ui.confirm=ui.create.control('ok');
					}
				}
				else if(str=='oc'||str=='co'){
					if(ui.confirm){
						ui.confirm.replace('ok','cancel');
					}
					else{
						ui.confirm=ui.create.control('ok','cancel');
					}
				}
				else if(str=='c'){
					if(ui.confirm){
						ui.confirm.replace('cancel');
					}
					else{
						ui.confirm=ui.create.control('cancel');
					}
				}
				else if(ui.confirm){
					ui.confirm.close();
					delete ui.confirm;
				}
				if(ui.confirm){
					ui.confirm.str=str;
					if(func) ui.confirm.custom=func;
					else delete ui.confirm.custom;
				}
			},
			skills:function(skills){
				var i,same;
				if(ui.skills){
					if(ui.skills.skills.length==skills.length&&ui.skills.style.display!='none'){
						same=true;
						for(i=0;i<skills.length;i++){
							if(ui.skills.skills.contains(skills[i])==false){
								same=false;
								break;
							}
						}
					}
					if(same) return;
					ui.skills.close();
					delete ui.skills;
				}
				if(skills==undefined||skills.length==0) return;
				if(!_status.event.isMine()){
					_status.noupdatec=true;
				}
				ui.skills=ui.create.control(skills.concat([ui.click.skill]));
				for(var i=0;i<ui.skills.childNodes.length;i++){
					ui.skills.childNodes[i].innerHTML=get.skillTranslation(ui.skills.childNodes[i].link,_status.event.player);
				}
				if(!_status.event.isMine()){
					ui.skills.style.display='none';
				}
				else{
					ui.updatec();
				}
				_status.noupdatec=false;
				ui.skills.skills=skills;
				return ui.skills;
			},
			skills2:function(skills){
				var i,same;
				if(ui.skills2){
					if(ui.skills2.skills.length==skills.length&&ui.skills2.style.display!='none'){
						same=true;
						for(i=0;i<skills.length;i++){
							if(ui.skills2.skills.contains(skills[i])==false){
								same=false;
								break;
							}
						}
					}
					if(same) return;
					ui.skills2.close();
					delete ui.skills2;
				}
				if(skills==undefined||skills.length==0) return;
				if(!_status.event.isMine()){
					_status.noupdatec=true;
				}
				ui.skills2=ui.create.control(skills.concat([ui.click.skill]));
				for(var i=0;i<ui.skills2.childNodes.length;i++){
					ui.skills2.childNodes[i].innerHTML=get.skillTranslation(ui.skills2.childNodes[i].link,_status.event.player);
				}
				if(!_status.event.isMine()){
					ui.skills2.style.display='none';
				}
				else{
					ui.updatec();
				}
				_status.noupdatec=false;
				ui.skills2.skills=skills;
				return ui.skills2;
			},
			skills3:function(skills){
				var i,same;
				if(ui.skills3){
					if(ui.skills3.skills.length==skills.length&&ui.skills3.style.display!='none'){
						same=true;
						for(i=0;i<skills.length;i++){
							if(ui.skills3.skills.contains(skills[i])==false){
								same=false;
								break;
							}
						}
					}
					if(same) return;
					ui.skills3.close();
					delete ui.skills3;
				}
				if(skills==undefined||skills.length==0) return;
				if(!_status.event.isMine()){
					_status.noupdatec=true;
				}
				ui.skills3=ui.create.control(skills.concat([ui.click.skill]));
				for(var i=0;i<ui.skills3.childNodes.length;i++){
					ui.skills3.childNodes[i].innerHTML=get.skillTranslation(ui.skills3.childNodes[i].link,_status.event.player);
				}
				if(!_status.event.isMine()){
					ui.skills3.style.display='none';
				}
				else{
					ui.updatec();
				}
				_status.noupdatec=false;
				ui.skills3.skills=skills;
				return ui.skills3;
			},
			arena:function(){
				var i,j;
				ui.window=ui.create.div('#window.hidden',document.body);
				ui.create.div('#statusbg',document.body);
				ui.refresh(ui.window);
				if(!localStorage.getItem(lib.configprefix+'playback')){
					ui.window.show();
				}
				else{
					setTimeout(function(){
						ui.window.show();
					},1000);
				}
				// lib.setPressure(ui.window,ui.click.pressurepause);
				if(window.isNonameServer){
					ui.window.classList.add('server');
					var serverinfo=ui.create.div('.serverinfo',ui.window);
					ui.create.div('','服务器正在运行',serverinfo);
					var serverinfotable=ui.create.table(2,2,ui.create.div(serverinfo));
					serverinfotable.style.display='inline-block';
					serverinfotable.firstChild.firstChild.innerHTML='房间人数:';
					serverinfotable.firstChild.lastChild.id='server_count';
					serverinfotable.firstChild.lastChild.innerHTML='0';
					serverinfotable.lastChild.firstChild.innerHTML='房间状态:';
					serverinfotable.lastChild.lastChild.id='server_status';
					serverinfotable.lastChild.lastChild.innerHTML='空闲';
					ui.create.div('.menubutton.large','关闭服务器',function(){
						if(_status.gameStarted&&!confirm('关闭服务器当前进行的游戏将终止且不可恢复,是否确定关闭?')){
							return;
						}
						localStorage.removeItem(lib.configprefix+'asserver');
						game.reload();
					},ui.create.div('',serverinfo));
				}

				ui.window.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.window);
				ui.system=ui.create.div("#system.",ui.window);
				ui.arena=ui.create.div('#arena.nome',ui.window);
				if(lib.device=='ios'&&!get.is.phoneLayout()){
					ui.arena.classList.add('ipad');
				}
				ui.arena.setNumber=function(num){
					this.dataset.number=num;
					// if(game.layout=='nova'&&parseInt(num)<7){
					// 	ui.arena.classList.add('player_autolong');
					// }
					// else if(lib.config.player_height_nova!='long'){
					// 	ui.arena.classList.remove('player_autolong');
					// }
					// if(game.layout=='long'&&parseInt(num)<parseInt(lib.config.fewplayer)){
					//     this.classList.add('fewplayer');
					// }
					// else{
					//     this.classList.remove('fewplayer');
					// }
				}

				if(lib.config.low_performance){
					ui.window.classList.add('low_performance');
				}
				if(game.layout=='mobile'||game.layout=='long'){
					ui.arena.classList.add('mobile');
				}
				if(game.layout=='long'||game.layout=='long2'){
					ui.arena.classList.add('long');
				}
				if(game.layout=='default'){
					ui.arena.classList.add('oldlayout');
				}
				if(lib.config.player_border!='wide'||game.layout=='long'||game.layout=='long2'){
					ui.arena.classList.add('slim_player');
				}
				if(lib.config.player_border=='slim'){
					ui.arena.classList.add('uslim_player');
				}
				if(lib.config.player_border=='narrow'){
					ui.arena.classList.add('mslim_player');
				}
				if(lib.config.player_border=='normal'&&lib.config.mode!='brawl'&&(game.layout=='long'||game.layout=='long2')){
					ui.arena.classList.add('lslim_player');
				}
				ui.window.dataset.player_border=lib.config.player_border;
				if(lib.config.compatiblemode){
					ui.window.classList.add('compatiblemode');
				}
				ui.window.dataset.radius_size=lib.config.radius_size||'default';
				if(game.layout=='long'||game.layout=='mobile'){
					//if(lib.config.textequip=='text') ui.arena.classList.add('textequip');
					ui.arena.classList.add('textequip');
				}
				if(game.layout=='long'||game.layout=='long2'||game.layout=='mobile'||game.layout=='nova'){
					if(lib.config.cardshape=='oblong'){
						ui.window.classList.add('oblongcard');
						ui.arena.classList.add('oblongcard');
					}
				}
				if(lib.config.blur_ui){
					ui.window.classList.add('blur_ui');
				}
				if(lib.config.glass_ui){
					ui.window.classList.add('glass_ui');
				}
				if(lib.config.custom_button){
					lib.configMenu.appearence.config.custom_button.onclick('skip');
				}

				if(lib.config.show_statusbar_ios=='overlay'){
					document.body.classList.add('statusbar');
				}
				if(lib.config.keep_awake){
					if(window.plugins&&window.plugins.insomnia) window.plugins.insomnia.keepAwake();
					else{
						lib.init.js(lib.assetURL+'game','NoSleep',function(){
							var noSleep = new NoSleep();
							document.addEventListener(lib.config.touchscreen?'touchend':'click', function enableNoSleep() {
								document.removeEventListener(lib.config.touchscreen?'touchend':'click', enableNoSleep, false);
								noSleep.enable();
								window.noSleep=noSleep;
							}, false);
						});
					}
				}
				lib.init.js(lib.assetURL+'game','pinyinjs',function(){})
				lib.init.js(lib.assetURL+'game','keyWords',function(){});
				
				lib.updateURL=lib.updateURLS[lib.config.update_link]||lib.updateURLS.coding;

				lib.init.cssstyles();

				ui.arena.dataset.player_height=lib.config.player_height||'default';
				ui.arena.dataset.player_height_nova=lib.config.player_height_nova||'default';
				// if(lib.config.player_height_nova=='long') ui.arena.classList.add('player_autolong');
				ui.arena.dataset.target_shake=lib.config.target_shake||'off';
				ui.backgroundMusic=document.createElement('audio');
				ui.backgroundMusic.volume=lib.config.volumn_background/8;
				game.playBackgroundMusic();
				ui.backgroundMusic.autoplay=true;
				ui.backgroundMusic.addEventListener('ended',game.playBackgroundMusic);
				ui.window.appendChild(ui.backgroundMusic);
				ui.window.addEventListener(lib.config.touchscreen?'touchend':'click', function playMusic() {
					ui.window.removeEventListener(lib.config.touchscreen?'touchend':'click', playMusic, false);
					if(!ui.backgroundMusic.played.length && lib.config.background_music != 'music_off') ui.backgroundMusic.play();
				}, false);
				if(lib.config.cursor_style=='pointer'){
					ui.window.classList.add('nopointer');
				}
				if(lib.config.turned_style==false){
					ui.arena.classList.add('hide_turned');
				}
				if(lib.config.link_style2!='chain'){
					ui.arena.classList.add('nolink');
				}
				if(lib.config.show_name==false){
					ui.arena.classList.add('hide_name');
				}
				if(lib.config.change_skin_auto!='off'){
					_status.skintimeout=setTimeout(ui.click.autoskin,parseInt(lib.config.change_skin_auto));
				}
				if(lib.config.border_style&&lib.config.border_style.startsWith('dragon_')){
					ui.arena.dataset.framedecoration=lib.config.border_style.slice(7);
				}

				ui.gameinfo=ui.create.div('#time',ui.window);

				ui.arenalog=ui.create.div('#arenalog',ui.arena);
				if(lib.config.show_log=='off'){
					ui.arenalog.style.display='none';
				}
				else{
					ui.arenalog.dataset.position=lib.config.show_log;
				}
				ui.historybar=ui.create.div('#historybar.shadowed',ui.window);
				lib.setScroll(ui.historybar);

				ui.roundmenu=ui.create.div('#roundmenu.roundarenabutton.menubutton.round',ui.arena);
				ui.roundmenu._position=[180,210];
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);

				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);

				ui.create.div(ui.roundmenu);
				ui.create.div(ui.roundmenu);

				ui.create.div(ui.roundmenu);

				if(lib.config.show_time2){
					ui.roundmenu.classList.add('clock');
				}
				ui.roundmenu.dataset.watchface=lib.config.watchface||'none';
				if(get.is.phoneLayout()){
					if(lib.config.show_time3){
						ui.time3=ui.create.div('.touchinfo.left',ui.window);
					}
					ui.cardPileNumber=ui.create.div('.touchinfo.right',ui.window);
				}
				else{
					if(lib.config.show_time3){
						ui.time3=ui.create.div(ui.gameinfo);
					}
					ui.cardPileNumber=ui.create.div(ui.gameinfo);
				}
				if(!lib.config.show_cardpile_number){
					ui.cardPileNumber.style.display='none';
				}
				if(ui.time3){
					ui.time3.starttime=get.utc();
					ui.time3.interval=setInterval(function(){
						var num=Math.round((get.utc()-ui.time3.starttime)/1000);
						if(num>=3600){
							var num1=Math.floor(num/3600);
							var num2=Math.floor((num-num1*3600)/60);
							if(num2<10){
								num2='0'+num2.toString();
							}
							var num3=num-num1*3600-parseInt(num2)*60;
							if(num3<10){
								num3='0'+num3.toString();
							}
							ui.time3.innerHTML=num1+':'+num2+':'+num3;
						}
						else{
							var num1=Math.floor(num/60);
							var num2=num-num1*60;
							if(num2<10){
								num2='0'+num2.toString();
							}
							ui.time3.innerHTML=num1+':'+num2;
						}
					},1000);
				}
				if(get.is.nomenu()){
					if(!['menu','system'].contains(lib.config.round_menu_func)){
						lib.config.round_menu_func='system';
					}
				}
				else if(!lib.config.show_round_menu){
					ui.roundmenu.style.display='none';
				}

				var resetround=function(e){
					_status.draggingroundmenu=false;
					ui.roundmenu.style.transform='';
					ui.roundmenu._dragtransform=[0,0];
					ui.roundmenu.style.transition='all 0.3s';
					delete ui.roundmenu._dragtouches;
					delete ui.roundmenu._dragorigin;
					delete ui.roundmenu._dragorigintransform;
					setTimeout(function(){
						ui.roundmenu.style.transition='';
					},500);
					game.saveConfig('roundmenu_transform',[0,0]);
					if(e) e.stopPropagation();
					return false;
				};
				ui.click.resetround=resetround;
				if(lib.config.touchscreen){
					ui.roundmenu.addEventListener('touchstart',function(e){
						_status.draggingroundmenu=true;
						ui.roundmenu._dragorigin={
							clientX:e.touches[0].clientX,
							clientY:e.touches[0].clientY,
						};
						if(!ui.roundmenu._dragtransform){
							ui.roundmenu._dragtransform=[0,0];
						}
						ui.roundmenu._dragorigintransform=ui.roundmenu._dragtransform.slice(0);
						ui.roundmenu._resetTimeout=setTimeout(function(){
							resetround();
							delete ui.roundmenu._resetTimeout;
						},1000);
					});
				}
				else{
					ui.roundmenu.oncontextmenu=resetround;
				}
				if(!lib.config.remember_round_button){
					game.saveConfig('roundmenu_transform');
				}
				if(lib.config.roundmenu_transform){
					var translate=lib.config.roundmenu_transform;
					ui.roundmenu._dragtransform=translate;
					ui.roundmenu.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)';
					ui.click.checkroundtranslate();
				}
				if(get.is.phoneLayout()){
					ui.arena.classList.add('phone');
				}

				ui.sidebar=ui.create.div('#sidebar');
				ui.sidebar3=ui.create.div('#sidebar3');
				ui.canvas=document.createElement('canvas');

				ui.arena.appendChild(ui.canvas);
				ui.canvas.id='canvas';
				ui.ctx=ui.canvas.getContext('2d');

				ui.sidebar.ontouchstart=ui.click.touchStart;
				ui.sidebar.ontouchmove = ui.click.touchScroll;
				ui.sidebar.style.WebkitOverflowScrolling='touch';

				var zoom;
				switch(lib.config.ui_zoom){
					case 'esmall':zoom=0.8;break;
					case 'vsmall':zoom=0.9;break;
					case 'small':zoom=0.93;break;
					case 'big':zoom=1.05;break;
					case 'vbig':zoom=1.1;break;
					case 'ebig':zoom=1.2;break;
					case 'eebig':zoom=1.5;break;
					case 'eeebig':zoom=1.8;break;
					case 'eeeebig':zoom=2;break;
					default:zoom=1;
				}
				game.documentZoom=game.deviceZoom*zoom;
				if(zoom!=1){
					ui.updatez();
				}

				ui.system1=ui.create.div('#system1',ui.system);
				ui.system2=ui.create.div('#system2',ui.system);

				ui.replay=ui.create.system('重来',game.reload,true);
				ui.replay.id='restartbutton';
				ui.config2=ui.create.system('选项',ui.click.config);
				ui.pause=ui.create.system('暂停',ui.click.pause);
				ui.pause.id='pausebutton';
				if(!_status.video){
					ui.pause.hide();
				}
				if(!lib.config.touchscreen){
					lib.setPopped(ui.pause,ui.click.pausehistory,220,400,null,true);
				}
				if(!lib.config.show_pause){
					ui.pause.style.display='none';
				}
				ui.cardPileButton=ui.create.system('牌堆',null,true);
				ui.cardPileButton.style.display='none';
				lib.setPopped(ui.cardPileButton,ui.click.cardPileButton,220);
				ui.wuxie=ui.create.system('不询问无懈',ui.click.wuxie,true);
				if(!lib.config.touchscreen){
					lib.setPopped(ui.config2,ui.click.pauseconfig,170);
				}
				ui.auto=ui.create.system('托管',ui.click.auto);
				if(!game.syncMenu){
					ui.config2.classList.add('hidden');
					ui.config2.style.transition='all 0.5s';
					ui.roundmenu.classList.add('transparent2');

					ui.auto.style.opacity=0.5;
					ui.auto.style.transition='all 0.5s';
					lib.onfree.push(function(){
						ui.auto.style.opacity='';
						setTimeout(function(){
							ui.auto.style.transition='';
						},500);
					});
				}
				ui.auto.id='autobutton';
				ui.autonode=ui.create.div('#autonode','<div>托管中...</div>',ui.arena);
				ui.autonode.listen(ui.click.auto);
				if(lib.config.mode=='connect'){
					ui.auto.hide();
					ui.pause.hide();
				}

				if(lib.forcehide){
					if(lib.forcehide.contains('replay')) ui.replay.classList.add('forcehide');
					if(lib.forcehide.contains('auto')) ui.auto.classList.add('forcehide');
					if(lib.forcehide.contains('pause')) ui.pause.classList.add('forcehide');
					if(lib.forcehide.contains('wuxie')) ui.wuxie.classList.add('forcehide');
					if(lib.forcehide.contains('cardPileButton')) ui.cardPileButton.classList.add('forcehide');
				}
				ui.volumn=ui.create.system('♫');
				lib.setPopped(ui.volumn,ui.click.volumn,200);
				// if(lib.config.show_pause) ui.auto.style.marginLeft='10px';
				if(!lib.config.show_volumn){
					ui.volumn.style.display='none';
				}
				if(!lib.config.show_auto){
					ui.auto.style.display='none';
				}
				if(!lib.config.show_wuxie){
					ui.wuxie.style.display='none';
				}
				// if(!lib.config.show_cardpile||_status.connectMode){
				// 	ui.cardPileButton.style.display='none';
				// }
				
				ui.sortCard=ui.create.system('整理手牌',function(){
					if(!game.me) return;
					var hs=game.me.getCards('h');
					if(!hs.length) return;
					game.addVideo('lose',game.me,[get.cardsInfo(hs),[],[],[]]);
					for(var i=0;i<hs.length;i++){
						hs[i].goto(ui.special);
					}
					if(game.me.hasSkillTag('sortCardByNum')){
						var getn=function(card){
							var num=get.number(card,game.me);
							if(num<3) return 13+num;
							return num;
						}
						hs.sort((a,b)=>(getn(b)-getn(a)));
					}
					else hs.sort(function(b,a){
						if(a.name!=b.name) return lib.sort.card(a.name,b.name);
						else if(a.suit!=b.suit) return lib.suit.indexOf(a)-lib.suit.indexOf(b);
						else return a.number-b.number;
					});
					game.me.directgain(hs,false);
				});
				if(!lib.config.show_sortcard){
					ui.sortCard.style.display='none';
				}
				ui.playerids=ui.create.system('显示身份',function(){
					if(game.showIdentity){
						game.showIdentity();
						_status.identityShown=true;
					}
				},true);
				if(!lib.config.show_playerids||!game.showIdentity){
					ui.playerids.style.display='none';
				}
				if(!lib.config.show_replay){
					ui.replay.style.display='none';
				}
				ui.control=ui.create.div('#control',ui.arena).animate('nozoom');
				ui.cardPile=ui.create.div('#cardPile');
				ui.discardPile=ui.create.div('#discardPile');
				ui.special=ui.create.div('#special');
				ui.ordering=ui.create.div('#ordering');
				ui.dialogs=[];
				ui.controls=[];
				ui.style={};

				ui.time=ui.create.div(ui.gameinfo);
				var timeInterval=function(){
					var date=new Date();
					var hours=date.getHours();
					var minutes=date.getMinutes();
					if(lib.config.watchface=='simple'){
						ui.roundmenu.childNodes[13].style.transform='rotate('+get.round((hours+9)*30,2)+'deg)';
					}
					else{
						ui.roundmenu.childNodes[13].style.transform='rotate('+get.round((hours+minutes/60+9)*30,2)+'deg)';
					}
					ui.roundmenu.childNodes[12].style.transform='rotate('+(minutes+45)*6+'deg)';
					if(minutes<10){
						minutes='0'+minutes.toString();
					}
					ui.time.innerHTML=hours+':'+minutes;
				};
				_status.timeInterval=setInterval(timeInterval,30000);
				timeInterval();
				if(!lib.config.show_time){
					ui.time.style.display='none';
				}

				ui.timer=ui.create.div('.skillbar.shadowed.playerbg.hidden');
				ui.timer.id='timer';
				ui.create.div('.skillbarshadow',ui.timer);
				ui.create.div('.skillbarfill',ui.timer);
				ui.timer.fillnode=ui.create.div(ui.timer.lastChild);
				ui.timer.popnode=ui.create.div('.skillbartext',ui.timer);
				ui.timer.popnode.style.opacity=1;
				ui.timer.position=4;
				ui.timer.style.zIndex=5;
				ui.timer.set=function(text,percentage){
					if(typeof text=='string'||typeof text=='number'){
						ui.timer.popnode.innerHTML=text;
					}
					ui.timer.fillnode.style.top=((1-percentage)*100)+'%';
				}
				var setTimerPosition=function(e){
					this.position++;
					if(this.position>4){
						this.position=1;
					}
					var left1='180px';
					var left2='calc(100% - 245px)';
					var top1='210px';
					var top2='calc(100% - 245px)';
					if(game.layout=='default'){
						left1='265px';
						top1='160px';
						left2='calc(100% - 330px)';
						top2='calc(100% - 235px)';
					}
					if(this.position==1||this.position==2){
						this.style.top=top2;
					}
					else{
						this.style.top=top1;
					}
					if(this.position==1||this.position==4){
						this.style.left=left2;
					}
					else{
						this.style.left=left1;
					}
				}
				ui.timer.listen(setTimerPosition);

				ui.shortcut=ui.create.div('#shortcut.hidden',ui.window);
				ui.shortcut.listen(ui.click.shortcut);
				ui.create.div(ui.shortcut,function(e){e.stopPropagation()});
				ui.create.div('.menubutton.round','<span>重来</span>',ui.shortcut,game.reload).dataset.position=1;
				ui.create.div('.menubutton.round','<span>退出</span>',ui.shortcut,game.exit).dataset.position=3;
				ui.create.div('.menubutton.round','<span>记录</span>',ui.shortcut,ui.click.pause).dataset.position=4;
				ui.shortcut.autobutton=ui.create.div('.menubutton.round','<span>托管</span>',ui.shortcut,ui.click.auto);
				ui.shortcut.autobutton.dataset.position=2;
				ui.favmodelist=ui.create.div('.favmodelist',ui.shortcut);
				ui.favmodelist.update=function(){
					const favouriteMode=lib.config.favouriteMode;
					let removed=false;
					for(let index=0;index<favouriteMode.length;index++){
						if(typeof favouriteMode[index]=='string') continue;
						favouriteMode.splice(index--,1);
						if(!removed) removed=true;
					}
					if(removed) game.saveConfigValue('favouriteMode');
					this.innerHTML='';
					favouriteMode.slice(0,6).forEach((value,index)=>this.add(value,index));
					let mode=lib.config.mode;
					const config=get.config(`${mode}_mode`);
					if(typeof config=='string') mode+=`|${config}`;
					if(favouriteMode.contains(mode)) ui.favmode.classList.add('glow');
					else ui.favmode.classList.remove('glow');
				};
				ui.favmodelist.add=function(name,index){
					const info=name.split('|'),mode=info[0],submode=info[1],node=ui.create.div('.menubutton.large',this),dataset=node.dataset;
					dataset.type=Math.min(6,lib.config.favouriteMode.length)%2==0?'even':'odd';
					dataset.position=index;
					let str=lib.translate[name]||lib.translate[mode]||'';
					if(str.length==2) str+='模式';
					node.innerHTML=str;
					node.listen(()=>{
						game.saveConfig('mode',mode);
						if(submode) game.saveConfig(`${mode}_mode`,submode,mode);
						game.reload();
					});
				};
				ui.favmode=ui.create.system('收藏',function(){
					const mode=typeof _status.mode=='string'?`${lib.config.mode}|${_status.mode}`:lib.config.mode;
					if(this.classList.contains('glow')){
						this.classList.remove('glow');
						lib.config.favouriteMode.remove(mode);
					}
					else{
						this.classList.add('glow');
						lib.config.favouriteMode.add(mode);
					}
					game.saveConfig('favouriteMode',lib.config.favouriteMode);
					ui.favmodelist.update();
					_status.clicked=true;
				});
				ui.favmode.style.display='none';
				ui.favmodelist.update();
				// ui.create.div('.menubutton.round','<span>菜单</span>',ui.shortcut,ui.click.config).dataset.position=5;


				if(_status.connectMode){
					ui.playerids.remove();
					ui.pause.innerHTML='记录';
				}
				setTimerPosition.call(ui.timer);
				ui.arena.appendChild(ui.timer);

				if(!game.syncMenu){
					lib.onfree.push(function(){
						ui.create.menu();
						ui.config2.classList.remove('hidden');
						ui.roundmenu.classList.remove('transparent2');
						setTimeout(function(){
							ui.config2.style.transition='';
						},500);
					});
				}
				else{
					ui.create.menu();
				}

				lib.status.date=new Date();
				lib.status.dateDelayed=0;

				while(lib.arenaReady.length){
					(lib.arenaReady.shift())();
				}
				delete lib.arenaReady;
				if(lib.config.auto_check_update){
					setTimeout(function(){
						game.checkForUpdate(false);
					},3000);
				}
				if(!lib.config.asset_version){
					lib.onfree.push(function(){
						setTimeout(function(){
							if(!game.download){
								game.saveConfig('asset_version','无');
							}
							else{
								var func=function(){
									if(confirm('是否下载图片和字体素材?(约175MB)')){
										if(!ui.arena.classList.contains('menupaused')){
											ui.click.configMenu();
											ui.click.menuTab('其它');
										}
										setTimeout(game.checkForAssetUpdate,500);
									}
									else{
										game.saveConfig('asset_version','无');
									}
								}
								if(_status.new_tutorial){
									_status.new_tutorial=func;
								}
								else{
									func();
								}
							}
						},3000);
					});
				}
				if(localStorage.getItem(lib.configprefix+'playback')){
					setTimeout(lib.init.onfree);
				}

				if(lib.config.test_game){
					ui.window.classList.add('testing');
					lib.config.game_speed='vfast';
					lib.config.low_performance=true;
					lib.config.animation=false;
					_status.auto=true;
					ui.auto.classList.add('glow');
					setTimeout(function(){
						var node=ui.create.pause().animate('start');
						node.appendChild(ui.sidebar);
						node.firstChild.innerHTML='正在测试';
						node.removeEventListener('click',ui.click.resume);
					},500);
				}
			},
			system:function(str,func,right,before){
				var parent=right?ui.system2:ui.system1;
				var node=ui.create.div();
				if(before){
					parent.insertBefore(node,parent.firstChild);
				}
				else{
					parent.appendChild(node);
				}
				node.innerHTML=str;
				if(func){
					node.listen(func);
				}
				if(lib.config.button_press){
					node.addEventListener(lib.config.touchscreen?'touchstart':'mousedown',function(e){
						if(!node.classList.contains('hidden')) node.classList.add('pressdown');
					});
					node.addEventListener(lib.config.touchscreen?'touchend':'mouseup',function(e){
						node.classList.remove('pressdown');
					});
					node.addEventListener(lib.config.touchscreen?'touchmove':'mousemove',function(e){
						node.classList.remove('pressdown');
					});
				}
				return node;
			},
			pause:function(){
				if(_status.pausing) return;
				ui.click.shortcut(false);
				var node=ui.create.div(".pausedbg",ui.window);
				_status.pausing=true;
				setTimeout(function(){
					_status.pausing=false;
				},500);
				if(lib.config.touchscreen){
					setTimeout(function(){
						node.addEventListener('touchend',ui.click.resume);
					},500);
				}
				else{
					node.addEventListener('click',ui.click.resume);
				}
				if(!lib.config.touchscreen){
					node.oncontextmenu=ui.click.resume;
				}

				var node2=ui.create.div(node);
				if(_status.connectMode){
					node2.innerHTML='';
				}
				else{
					node2.innerHTML='已暂停';
				}

				// node2.listen(function(){
				// 	_status.clicked=true;
				// 	if(ui.sidebar.classList.contains('hidden')){
				// 		ui.sidebar.show();
				// 		ui.sidebar3.show();
				// 	}
				// 	else{
				// 		ui.sidebar.hide();
				// 		ui.sidebar3.hide();
				// 	}
				// });
				return node;
			},
			prebutton:function(item,type,position,noclick){
				var node=ui.create.div(position);
				node.style.display='none';
				node.link=item;
				node.activate=function(){
					ui.create.button(item,type,position,noclick,node);
					delete node.activate;
				}
				_status.prebutton.push(node);
				return node;
			},
			buttonPresets:{
				tdnodes:(item,type,position,noclick,node)=>{
					node=ui.create.div('.shadowed.reduce_radius.pointerdiv.tdnode.tdnodes',position);
					if(Array.isArray(item)){
						node.innerHTML='<span>'+(item[1])+'</span>';
						node.link=item[0];
					}
					else{
						node.innerHTML='<span>'+(item)+'</span>';
						node.link=item;
					}
					return node;
				},
				blank:(item,type,position,noclick,node)=>{
					node=ui.create.div('.button.card',position);
					node.link=item;
					return node;
				},
				card:(item,type,position,noclick,node)=>{
					if(typeof item.copy=='function'){
						node=item.copy(false);
					}
					else{
						node=item.cloneNode(true);
					}
					node.classList.add('button');
					if(position) position.appendChild(node);
					node.link=item;
					if(item.style.backgroundImage){
						node.style.backgroundImage=item.style.backgroundImage;
						node.style.backgroundSize='cover';
					}
					if(item.style.color){
						node.style.color=item.style.color;
					}
					if(item.nature){
						let natures=get.natureList(item.nature);
						natures.forEach(n=>node.classList.add(n));
					}
					if(!noclick){
						lib.setIntro(node);
					}
					if(get.position(item)=='j'&&item.viewAs&&item.viewAs!=item.name&&lib.config.cardtempname!='off'){
						ui.create.cardTempName(item,node);
					}
					return node;
				},
				vcard:(item,type,position,noclick,node)=>{
					if(typeof item=='string'){
						item=[get.type(item),'',item];
					}
					node=ui.create.card(position,'noclick',noclick);
					node.classList.add('button');
					node.init(item);
					node.link=item;
					return node;
				},
				character:(item,type,position,noclick,node)=>{
					if(node){
						node.classList.add('button');
						node.classList.add('character');
						node.style.display='';
					}
					else{
						node=ui.create.div('.button.character',position);
					}
					node._link=item;
					if(_status.noReplaceCharacter&&type=='characterx') type='character';
					if(type=='characterx'){
						if(lib.characterReplace[item]&&lib.characterReplace[item].length) item=lib.characterReplace[item].randomGet();
					}
					node.link=item;

					var double=get.is.double(node._link,true);
					if(double) node._changeGroup=true;
					if(type=='characterx'&&lib.characterReplace[node._link]&&lib.characterReplace[node._link].length>1) node._replaceButton=true;
					var func=function(node,item){
						node.setBackground(item,'character');
						if(node.node){
							node.node.name.remove();
							node.node.hp.remove();
							node.node.group.remove();
							node.node.intro.remove();
							if(node.node.replaceButton) node.node.replaceButton.remove();
						}
						node.node={
							name:ui.create.div('.name',node),
							hp:ui.create.div('.hp',node),
							group:ui.create.div('.identity',node),
							intro:ui.create.div('.intro',node),
						};
						var infoitem=lib.character[item];
						if(!infoitem){
							for(var itemx in lib.characterPack){
								if(lib.characterPack[itemx][item]){
									infoitem=lib.characterPack[itemx][item];break;
								}
							}
						}
						node.node.name.innerHTML=get.slimName(item);
						if(lib.config.buttoncharacter_style=='default'||lib.config.buttoncharacter_style=='simple'){
							if(lib.config.buttoncharacter_style=='simple'){
								node.node.group.style.display='none';
							}
							node.classList.add('newstyle');
							node.node.name.dataset.nature=get.groupnature(get.bordergroup(infoitem));
							node.node.group.dataset.nature=get.groupnature(get.bordergroup(infoitem),'raw');
							ui.create.div(node.node.hp);
							var hp=get.infoHp(infoitem[2]),maxHp=get.infoMaxHp(infoitem[2]),hujia=get.infoHujia(infoitem[2]);
							var str=get.numStr(hp);
							if(hp!=maxHp){
								str+='/';
								str+=get.numStr(maxHp);
							}
							var textnode=ui.create.div('.text',str,node.node.hp);
							if(infoitem[2]==0){
								node.node.hp.hide();
							}
							else if(get.infoHp(infoitem[2])<=3){
								node.node.hp.dataset.condition='mid';
							}
							else{
								node.node.hp.dataset.condition='high';
							}
							if(hujia>0){
								ui.create.div(node.node.hp,'.shield');
								ui.create.div('.text',get.numStr(hujia),node.node.hp);
							}
						}
						else{
							var hp=get.infoHp(infoitem[2]);
							var maxHp=get.infoMaxHp(infoitem[2]);
							var shield=get.infoHujia(infoitem[2]);
							if(maxHp>14){
								if(typeof infoitem[2]=='string') node.node.hp.innerHTML=infoitem[2];
								else node.node.hp.innerHTML=get.numStr(infoitem[2]);
								node.node.hp.classList.add('text');
							}
							else{
								for(var i=0;i<maxHp;i++){
									var next=ui.create.div('',node.node.hp);
									if(i>=hp) next.classList.add('exclude');
								}
								for(var i=0;i<shield;i++){
									ui.create.div(node.node.hp,'.shield');
								}
							}
						}
						if(node.node.hp.childNodes.length==0){
							node.node.name.style.top='8px';
						}
						if(node.node.name.querySelectorAll('br').length>=4){
							node.node.name.classList.add('long');
							if(lib.config.buttoncharacter_style=='old'){
								node.addEventListener('mouseenter',ui.click.buttonnameenter);
								node.addEventListener('mouseleave',ui.click.buttonnameleave);
							}
						}
						node.node.intro.innerHTML=lib.config.intro;
						if(!noclick){
							lib.setIntro(node);
						}
						if(infoitem[1]){
							if(double){
								node.node.group.innerHTML=double.reduce((previousValue,currentValue)=>`${previousValue}<div data-nature="${get.groupnature(currentValue)}">${get.translation(currentValue)}</div>`,'');
								if(double.length>4) if(new Set([5,6,9]).has(double.length)) node.node.group.style.height='48px';
								else node.node.group.style.height='64px';
							}
							else node.node.group.innerHTML=`<div>${get.translation(infoitem[1])}</div>`;
							node.node.group.style.backgroundColor=get.translation(`${get.bordergroup(infoitem)}Color`);
						}
						else{
							node.node.group.style.display='none';
						}
						if(node._replaceButton){
							var intro=ui.create.div('.button.replaceButton',node);
							node.node.replaceButton=intro;
							intro.innerHTML='切换';
							intro._node=node;
							intro.addEventListener(lib.config.touchscreen?'touchend':'click',function(){
								_status.tempNoButton=true;
								var node=this._node;
								var list=lib.characterReplace[node._link];
								var link=node.link;
								var index=list.indexOf(link);
								if(index==list.length-1) index=0;
								else index++;
								link=list[index];
								node.link=link;
								node.refresh(node,link);
								setTimeout(function(){
									delete _status.tempNoButton;
								},200);
							});
						}
					};
					node.refresh=func;
					node.refresh(node,item);
					
					return node;
				},
				characterx:(item,type,position,noclick,node)=>{
					return ui.create.buttonPresets.character(item,type,position,noclick,node);
				},
				player:(item,type,position,noclick,node)=>{
					if(node){
						node.classList.add('button');
						node.classList.add('character');
						node.style.display='';
					}
					else{
						node=ui.create.div('.button.character',position);
					}
					node._link=item;
					node.link=item;
					node.node={
						name:ui.create.div('.name',node),
						intro:ui.create.div('.intro',node)
					}
					if(item.name&&item.name.startsWith('unknown')){
						if(item.node&&item.node.name_seat){
							node.classList.add('cardbg');
							ui.create.div('.avatar_name',node,get.translation(item.name));
						}
						else{
							node.setBackground(item.name1,'character');
						}
					}
					else{
						node.setBackground(item.name,'character');
					}
					return node;
				}
			},
			button:function(item,type,position,noclick,node){
				if(ui.create.buttonPresets[type]){
					node=ui.create.buttonPresets[type](item,type,position,noclick,node);
				}
				else if(typeof type=='function'){
					node=type(item,type,position,noclick,node);
				}
				if(!noclick){
					node.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.button);
				}
				else{
					node.classList.add('noclick');
					if(node.querySelector('.intro')){
						node.querySelector('.intro').remove();
					}
				}
				for(var i in lib.element.button){
					node[i]=lib.element.button[i];
				}
				return node;
			},
			buttons:function(list,type,position,noclick,zoom){
				var buttons=[];
				var pre=(typeof type=='string'&&type.slice(0,3)=='pre');
				if(pre){
					if(!_status.prebutton){
						_status.prebutton=[];
						lib.onfree.push(function(){
							for(var i=0;i<_status.prebutton.length;i++){
								if(_status.prebutton[i].activate){
									_status.prebutton[i].activate();
								}
							}
							delete _status.prebutton;
						});
					}
				}
				for(var i=0;i<list.length;i++){
					if(pre){
						buttons.push(ui.create.prebutton(list[i],type.slice(3),position,noclick));
					}
					else{
						buttons.push(ui.create.button(list[i],type,position,noclick));
					}
				}
				return buttons;
			},
			textbuttons:function(list,dialog,noclick){
				for(var item of list){
					var str,link;
					if(Array.isArray(item)){
						str=item[1];
						link=item[0];
					}
					else{
						str=item;
						link=item;
					}
					if(!str.startsWith('<div')) str='<div class="popup text textbutton">'+str+'</div>';
					var next=dialog.add(str);
					if(!noclick) next.firstChild.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.button);
					next.firstChild.link=link;
					for(var j in lib.element.button){
						next[j]=lib.element.button[j];
					}
					dialog.buttons.add(next.firstChild)
				}
			},
			player:function(position,noclick){
				var node=ui.create.div('.player',position);
				node.node={
					avatar:ui.create.div('.avatar',node,ui.click.avatar).hide(),
					avatar2:ui.create.div('.avatar2',node,ui.click.avatar2).hide(),
					turnedover:ui.create.div('.turned','<div>'+get.verticalStr('翻面')+'<div>',node),
					framebg:ui.create.div('.framebg',node),
					intro:ui.create.div('.intro',node),
					identity:ui.create.div('.identity',node),
					hp:ui.create.div('.hp',node),
					name:ui.create.div('.name',node),
					name2:ui.create.div('.name.name2',node),
					nameol:ui.create.div('.nameol',node),
					count:ui.create.div('.count',node).hide(),
					equips:ui.create.div('.equips',node).hide(),
					judges:ui.create.div('.judges',node),
					marks:ui.create.div('.marks',node),
					chain:ui.create.div('.chain','<div></div>',node),
					handcards1:ui.create.div('.handcards'),
					handcards2:ui.create.div('.handcards'),
					expansions:ui.create.div('.expansions'),
				};
				node.node.expansions.display='none';
				var chainlength=game.layout=='default'?64:40;
				for(var i=0;i<chainlength;i++){
					ui.create.div(node.node.chain.firstChild,'.cardbg').style.transform='translateX('+(i*5-5)+'px)';
				}
				node.node.action=ui.create.div('.action',node.node.avatar);

				node.phaseNumber=0;
				node.skipList=[];
				node.skills=[];
				node.invisibleSkills=[];
				node.initedSkills=[];
				node.additionalSkills={};
				node.disabledSkills={};
				node.hiddenSkills=[];
				node.awakenedSkills=[];
				node.forbiddenSkills={};
				node.popups=[];
				node.damagepopups=[];
				node.judging=[];
				node.stat=[{card:{},skill:{}}];
				node.actionHistory=[{useCard:[],respond:[],skipped:[],lose:[],gain:[],sourceDamage:[],damage:[],custom:[],useSkill:[]}];
				node.tempSkills={};
				node.storage={};
				node.marks={};
				node.expandedSlots={};
				node.disabledSlots={};
				node.ai={friend:[],enemy:[],neutral:[],handcards:{global:[],source:[],viewed:[]}};
				node.queueCount=0;
				node.outCount=0;

				for(var i in lib.element.player){
					node[i]=lib.element.player[i];
				}
				node.node.link=node.mark(' ',{mark:get.linkintro});
				node.node.link.firstChild.setBackgroundImage('image/card/tiesuo_mark.png')
				node.node.link.firstChild.style.backgroundSize='cover';
				ui.create.div(node.node.identity);
				if(!noclick){
					node.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.target);
					node.node.identity.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.identity);
					if(lib.config.touchscreen){
						node.addEventListener('touchstart',ui.click.playertouchstart);
					}
				}
				else node.noclick=true;

				return node;
			},
			connectPlayers:function(ip){
				game.connectPlayers=[];
				for(var i=0;i<8;i++){
					var player=ui.create.player(ui.window);
					player.dataset.position=i;
					player.classList.add('connect');
					game.connectPlayers.push(player);
					if(i>=lib.configOL.number){
						player.classList.add('unselectable2');
					}
				}

				var bar=ui.create.div(ui.window);
				bar.style.height='20px';
				bar.style.width='80%';
				bar.style.left='10%';
				bar.style.top='calc(200% / 7 - 120px + 5px)';
				bar.style.textAlign='center';
				var ipbar=ui.create.div('.shadowed',ip,bar);
				ipbar.style.padding='4px';
				ipbar.style.borderRadius='2px';
				ipbar.style.position='relative';

				var button=ui.create.div('.menubutton.large.highlight.connectbutton.pointerdiv',game.online?'退出联机':'开始游戏',ui.window,function(){
					if(button.clicked) return;
					if(game.online){
						if(game.onlinezhu){
							game.send('startGame');
						}
						else{
							game.saveConfig('tmp_owner_roomId');
							game.saveConfig('tmp_user_roomId');
							game.saveConfig('reconnect_info');
							game.reload();
						}
					}
					else{
						var num=0;
						for(var i of game.connectPlayers){
							if(!i.nickname&&!i.classList.contains('unselectable2')) num++;
						}
						if(num>=lib.configOL.number-1){
							alert('至少要有两名玩家才能开始游戏!');
							return;
						}
						game.resume();
					}
					button.delete();
					bar.delete();
					delete ui.connectStartButton;
					delete ui.connectStartBar;
					button.clicked=true;
				});

				ui.connectStartButton=button;
				ui.connectStartBar=bar;
			},
			players:function(num){
				if(num===0){
					return;
				}
				if(num==undefined) num=lib.configOL.number;
				if(num==undefined) num=get.playerNumber();
				if(typeof num=='string'){
					num=parseInt(num);
				}
				if(!num) num=5;
				for(var i=0;i<num;i++){
					var player=ui.create.player().animate('start');
					game.players.push(player);
					player.dataset.position=i;
				}
				var players=game.players;
				for(var i=0;i<players.length;i++){
					if(i>0){
						players[i].previous=players[i-1];
						players[i].previousSeat=players[i-1];
					}
					if(i<players.length-1){
						players[i].next=players[i+1];
						players[i].nextSeat=players[i+1];
					}
				}
				players[0].previous=players[players.length-1];
				players[0].previousSeat=players[players.length-1];
				players[players.length-1].next=players[0];
				players[players.length-1].nextSeat=players[0];
				ui.arena.setNumber(num);
				for(var i=0;i<num;i++){
					ui.arena.appendChild(players[i]);
				}
				// ui.arena.classList.add('glass');
				// for(var i=0;i<num;i++){
				// 	var bg=ui.create.div('.glassbg');
				// 	var bg2=ui.create.div(bg);
				// 	ui.create.div(bg);
				// 	var rect=players[i].getBoundingClientRect();
				// 	bg2.style.backgroundImage='url("image/background/huangtian_bg.jpg")';
				// 	bg2.style.width=ui.window.offsetWidth+'px';
				// 	bg2.style.height=ui.window.offsetHeight+'px';
				// 	bg2.style.transform='translate('+(-rect.left)+'px,'+(-rect.top)+'px)';
				// 	players[i].insertBefore(bg,players[i].firstChild);
				// }
				return players;
			},
			me:function(hasme){
				ui.mebg=ui.create.div('#mebg',ui.arena);
				ui.me=ui.create.div('#me',ui.arena).animate('start');
				ui.handcards1Container=ui.create.div('#handcards1',ui.me);
				ui.handcards2Container=ui.create.div('#handcards2',ui.me);
				ui.arena.classList.remove('nome');
				if(lib.config.mousewheel&&!lib.config.touchscreen){
					ui.handcards1Container.onmousewheel=ui.click.mousewheel;
					ui.handcards2Container.onmousewheel=ui.click.mousewheel;
				}
				ui.handcards1Container.ontouchstart = ui.click.touchStart;
				ui.handcards2Container.ontouchstart = ui.click.touchStart;
				ui.handcards1Container.ontouchmove = ui.click.touchScroll;
				ui.handcards2Container.ontouchmove = ui.click.touchScroll;
				ui.handcards1Container.style.WebkitOverflowScrolling='touch';
				ui.handcards2Container.style.WebkitOverflowScrolling='touch';

				if(hasme&&game.me){
					ui.handcards1=game.me.node.handcards1;
					ui.handcards2=game.me.node.handcards2;
					ui.handcards1Container.appendChild(ui.handcards1);
					ui.handcards2Container.appendChild(ui.handcards2);
					// ui.updatehl();
				}
				else if(game.players.length){
					game.me=game.players[0];
					ui.handcards1=game.me.node.handcards1;
					ui.handcards2=game.me.node.handcards2;
					ui.handcards1Container.appendChild(ui.handcards1);
					ui.handcards2Container.appendChild(ui.handcards2);
					// ui.updatehl();
				}
			},
			card:function(position,info,noclick){
				var node=ui.create.div('.card',position);
				node.node={
					image:ui.create.div('.image',node),
					info:ui.create.div('.info',node),
					name:ui.create.div('.name',node),
					name2:ui.create.div('.name2',node),
					background:ui.create.div('.background',node),
					intro:ui.create.div('.intro',node),
					range:ui.create.div('.range',node),
					gaintag:ui.create.div('.gaintag',node),
				}
				for(var i in lib.element.card){
					node[i]=lib.element.card[i];
				}
				node.node.intro.innerHTML=lib.config.intro;
				if(!noclick){
					lib.setIntro(node);
				}
				node.storage={};
				node.vanishtag=[];
				node.gaintag=[];
				node._uncheck=[];
				if(info!='noclick'){
					node.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.card);
					if(lib.config.touchscreen){
						node.addEventListener('touchstart',ui.click.cardtouchstart);
						node.addEventListener('touchmove',ui.click.cardtouchmove);
					}
					if(lib.cardSelectObserver){
						lib.cardSelectObserver.observe(node,{attributes:true});
					}
				}
				return node;
			},
			cardsAsync:function(){
				if(lib.onfree){
					_status.waitingForCards=Array.from(arguments);
					lib.onfree.push(function(){
						if(_status.waitingForCards){
							ui.create.cards.apply(ui.create,_status.waitingForCards);
							delete _status.waitingForCards;
						}
					});
				}
				else{
					ui.create.cards.apply(ui.create,arguments);
				}
			},
			cards:function(ordered){
				if(_status.brawl){
					if(_status.brawl.cardPile){
						lib.card.list=_status.brawl.cardPile(lib.card.list);
					}
					if(_status.brawl.orderedPile){
						ordered=true;
					}
				}
				if(!ordered){
					lib.card.list.randomSort();
				}
				for(var i=0;i<lib.card.list.length;i++){
					if(lib.card[lib.card.list[i][2]]){
						if(!lib.card.list[i]._replaced){
							if(!_status.connectMode){
								if(lib.config.bannedcards.contains(lib.card.list[i][2])) continue;
							}
							else{
								if(lib.configOL.bannedcards.contains(lib.card.list[i][2])) continue;
							}
							if(game.bannedcards&&game.bannedcards.contains(lib.card.list[i][2])) continue;
						}
						lib.inpile.add(lib.card.list[i][2]);
						if(lib.card.list[i][2]=='sha'&&lib.card.list[i][3]) lib.inpile_nature.add(lib.card.list[i][3]);
						ui.create.card(ui.cardPile).init(lib.card.list[i]);
					}
				}
				lib.inpile.sort(lib.sort.card);
				const natures=Array.from(lib.nature.keys());
				lib.inpile_nature.sort(function(a,b){
					return natures.indexOf(a)-natures.indexOf(b);
				})
				for(var i in _status.cardtag){
					if(!_status.cardtag[i].length) delete _status.cardtag[i];
				}
				game.broadcastAll(function(num,pile,top,cardtag,inpile2){
					if(ui.cardPileNumber) ui.cardPileNumber.innerHTML='0轮 剩余牌: '+num;
					lib.inpile=pile;
					_status.pileTop=top;
					_status.cardtag=cardtag;
					lib.inpile_nature=inpile2;
				},ui.cardPile.childNodes.length,lib.inpile,ui.cardPile.firstChild,_status.cardtag,lib.inpile_nature);
			},
		},
		click:{
			identitycircle:function(){
				var list=[];
				this.classList.toggle('transparent');
				for(var i=0;i<this.parentNode.childNodes.length;i++){
					if(!this.parentNode.childNodes[i].classList.contains('transparent')){
						list.add(this.parentNode.childNodes[i].link[2]);
					}
				}
				var info=this.link;
				if(list.length==1){
					for(var i=0;i<this.parentNode.childNodes.length;i++){
						if(!this.parentNode.childNodes[i].classList.contains('transparent')){
							var info2=this.parentNode.childNodes[i].link;
							info[0].firstChild.innerHTML=info2[1];
							info[0].dataset.color=info2[2];
						}
					}
				}
				else{
					info[0].firstChild.innerHTML='';
					info[0].dataset.color='';
					ui.create.identitycircle(list,info[0].firstChild);
				}
				this._source._guozhanguess=list;
			},
			connectEvents:function(){
				if(this.info){
					var button=this;
					var layer=ui.create.div('.poplayer',ui.window);
					var uiintro=ui.create.dialog('hidden','notouchscroll');
					this.classList.add('active');
					if(lib.config.touchscreen){
						lib.setScroll(uiintro.contentContainer);
					}
					layer.listen(function(){
						if(this.clicked){
							this.clicked=false;
							return;
						}
						button.classList.remove('active');
						uiintro.delete();
						this.delete();
					});
					uiintro.listen(function(){
						_status.clicked=true;
					});
					uiintro.style.zIndex=21;
					uiintro.classList.add('popped');
					uiintro.classList.add('static');
					uiintro.classList.add('onlineclient');
					uiintro.style.width='180px';
					uiintro.style.height='300px';
					uiintro.style.left='auto';
					uiintro.style.right='20px';
					uiintro.style.top='auto';
					uiintro.style.bottom='75px';

					uiintro.refresh=function(){
						if(button.focused) return;
						uiintro.content.innerHTML='';
						uiintro.addText('创建约战');
						button.textnode=uiintro.content.lastChild.lastChild;
						uiintro.add('<input type="text" style="width:calc(100% - 10px);resize: none;border: none;border-radius: 2px;box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 0px 1px;margin-top: -2px;margin-bottom: 2px;">');
						uiintro.content.lastChild.style.paddingTop=0;
						button.input=uiintro.content.lastChild.lastChild;
						button.input.onfocus=function(){
							button.focused=true;
						}
						button.input.onblur=function(){
							delete button.focused;
						}
						if(button.interval){
							button.input.disabled=true;
							button.input.style.opacity=0.6;
							if(button.intervaltext){
								button.textnode.innerHTML=button.intervaltext;
							}
						}
						var datenode=ui.create.div(uiintro.content);
						datenode.style.marginTop=0;
						datenode.style.whiteSpace='nowrap';
						var date=new Date();
						var days=[];
						var currentDay=date.getDay();
						if(currentDay==0) currentDay=7;
						for(var i=1;i<=7;i++){
							if(i<currentDay){
								days.push([i.toString(),'下周'+get.cnNumber(i,true)]);
							}
							else if(i==7){
								days.push([i.toString(),'周日']);
							}
							else if(i==currentDay){
								days.push([i.toString(),'今天']);
							}
							else{
								days.push([i.toString(),'周'+get.cnNumber(i,true)]);
							}
						}
						days=days.concat(days.splice(0,currentDay-1));
						var initday=currentDay+1;
						if(initday>7){
							initday-=7;
						}
						var daysselect=ui.create.selectlist(days,initday.toString(),datenode);
						daysselect.style.width='55px';
						var hours=[];
						for(var i=0;i<24;i++){
							hours.push([i.toString(),i.toString()+'点']);
						}
						var hoursselect=ui.create.selectlist(hours,date.getHours().toString(),datenode);
						hoursselect.style.marginLeft='5px';
						hoursselect.style.width='55px';
						var timeconfirm=ui.create.node('button','确定',datenode);
						timeconfirm.style.marginLeft='5px';
						timeconfirm.onclick=function(){
							if(!button.input.value){
								alert('请填写约战标题');
								return;
							}
							var date2=new Date();
							date2.setHours(parseInt(hoursselect.value));
							date2.setMinutes(0);
							date2.setSeconds(0);
							var deltaday=parseInt(daysselect.value)-currentDay;
							if(deltaday<0){
								deltaday+=7;
							}
							var utc=date2.getTime()+deltaday*24*3600000;
							if(utc<date.getTime()){
								alert('创建失败,时间已过');
								return;
							}
							if(get.is.banWords(button.input.value)){
								var eventnode=ui.create.div('.menubutton.videotext.onlineevent.pointerdiv',function(){
									var that=this;
									setTimeout(function(){
										if(that.classList.contains('active')){
											if(confirm('确定要离开'+that.info.content+'?')){
												that.classList.remove('active');
											}
										}
										else{
											if(confirm('确定要加入'+that.info.content+'?')){
												that.classList.add('active');
											}
										}
									});
								},uiintro.content,4);
								var fakeinfo={
									utc:utc,
									day:parseInt(daysselect.value),
									hour:parseInt(hoursselect.value),
									nickname:get.connectNickname(),
									avatar:lib.config.connect_avatar,
									content:button.input.value,
									create:game.onlineKey,
									members:[game.onlineKey],
								};
								eventnode.info=fakeinfo;
								ui.create.div('.title',fakeinfo.content,eventnode);
								var str;
								if(fakeinfo.day<currentDay){
									str='下周';
								}
								else{
									str='周';
								}
								if(fakeinfo.day==7){
									str+='日'
								}
								else{
									str+=get.cnNumber(fakeinfo.day,true);
								}
								str+=' ';
								var hour=fakeinfo.hour;
								if(hour<=12){
									if(hour<=5){
										str+='凌晨';
									}
									else if(hour<12){
										str+='上午';
									}
									else{
										str+='中午';
									}
									str+=fakeinfo.hour+'点';
								}
								else{
									if(hour<=17){
										str+='下午';
									}
									else{
										str+='晚上';
									}
									str+=(fakeinfo.hour-12)+'点';
								}
								ui.create.div('','已有'+(fakeinfo.members.length)+'人加入',eventnode);
								ui.create.div('','时间:'+str,eventnode);
								if(fakeinfo.members.contains(game.onlineKey)){
									eventnode.classList.add('active');
								}
								button.input.value='';
								return;
							}
							game.send('server','events',{
								utc:utc,
								day:parseInt(daysselect.value),
								hour:parseInt(hoursselect.value),
								nickname:get.connectNickname(),
								avatar:lib.config.connect_avatar,
								content:button.input.value
							},game.onlineKey);
						};

						var num=0;
						for(var i=0;i<button.info.length;i++){
							if(typeof button.info[i].creator=='string'&&button.info[i].creator!=game.onlineKey&&get.is.banWords(button.info[i].content)) continue;
							if(button.info[i].creator==game.onlineKey){
								num++;
							}
							var eventnode=ui.create.div('.menubutton.videotext.onlineevent.pointerdiv',function(){
								var that=this;
								if(typeof that.info.creator!='string') return;
								setTimeout(function(){
									if(that.classList.contains('active')){
										if(confirm('确定要离开'+that.info.content+'?')){
											game.send('server','events',that.info.id,game.onlineKey,'leave');
										}
									}
									else{
										if(confirm('确定要加入'+that.info.content+'?')){
											game.send('server','events',that.info.id,game.onlineKey,'join');
										}
									}
								});
							},uiintro.content);
							eventnode.info=button.info[i];
							if(typeof button.info[i].creator=='string'){
								ui.create.div('.title',button.info[i].content,eventnode);
								var str;
								if(button.info[i].day<currentDay){
									str='下周';
								}
								else{
									str='周';
								}
								if(button.info[i].day==7){
									str+='日'
								}
								else{
									str+=get.cnNumber(button.info[i].day,true);
								}
								str+=' ';
								var hour=button.info[i].hour;
								if(hour<=12){
									if(hour<=5){
										str+='凌晨';
									}
									else if(hour<12){
										str+='上午';
									}
									else{
										str+='中午';
									}
									str+=button.info[i].hour+'点';
								}
								else{
									if(hour<=17){
										str+='下午';
									}
									else{
										str+='晚上';
									}
									str+=(button.info[i].hour-12)+'点';
								}
								ui.create.div('','创建者:'+(button.info[i].nickname),eventnode);
								//ui.create.div('','创建者:'+(button.info[i].nickname)+'<br>ID:'+button.info[i].creator,eventnode);
								ui.create.div('','已有'+(button.info[i].members.length)+'人加入',eventnode);
								ui.create.div('','时间:'+str,eventnode);
								if(button.info[i].members.contains(game.onlineKey)){
									eventnode.classList.add('active');
								}
							}
							else{
								ui.create.div('.title',button.info[i].title,eventnode);
								ui.create.div('',button.info[i].content,eventnode);
								ui.create.div('','创建者:'+(button.info[i].nickname),eventnode);
							}
						}
						if(num>=3){
							button.input.disabled=true;
							button.input.style.opacity=0.6;
							hoursselect.disabled=true;
							daysselect.disabled=true;
							timeconfirm.disabled=true;
						}
					}
					uiintro.refresh();
					ui.window.appendChild(uiintro);
					_status.connectEventsCallback=function(){
						if(uiintro.parentNode==ui.window){
							uiintro.refresh();
						}
					};
				}
			},
			connectClients:function(){
				if(this.info){
					var button=this;
					var layer=ui.create.div('.poplayer',ui.window);
					var uiintro=ui.create.dialog('hidden','notouchscroll');
					this.classList.add('active');
					if(lib.config.touchscreen){
						lib.setScroll(uiintro.contentContainer);
					}
					layer.listen(function(){
						if(this.clicked){
							this.clicked=false;
							return;
						}
						button.classList.remove('active');
						uiintro.delete();
						this.delete();
					});
					uiintro.listen(function(){
						_status.clicked=true;
					});
					uiintro.style.zIndex=21;
					uiintro.classList.add('popped');
					uiintro.classList.add('static');
					uiintro.classList.add('onlineclient');
					uiintro.style.width='180px';
					uiintro.style.height='300px';
					uiintro.style.left='auto';
					uiintro.style.right='20px';
					uiintro.style.top='auto';
					uiintro.style.bottom='75px';

					uiintro.refresh=function(){
						if(button.focused) return;
						uiintro.content.innerHTML='';
						uiintro.addText('发状态');
						button.textnode=uiintro.content.lastChild.lastChild;
						uiintro.add('<input type="text" style="width:calc(100% - 10px);resize: none;border: none;border-radius: 2px;box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 0px 1px;margin-top: -2px;margin-bottom: 2px;">');
						uiintro.content.lastChild.style.paddingTop=0;
						button.input=uiintro.content.lastChild.lastChild;
						button.input.onfocus=function(){
							button.focused=true;
						}
						button.input.onblur=function(){
							delete button.focused;
						}
						if(button.interval){
							button.input.disabled=true;
							button.input.style.opacity=0.6;
							if(button.intervaltext){
								button.textnode.innerHTML=button.intervaltext;
							}
						}
						button.input.onkeydown=function(e){
							if(e.keyCode==13&&!this.disabled){
								game.send('server','status',this.value);
								this.blur();
								this.disabled=true;
								this.style.opacity=0.6;
								button.textnode.innerHTML='发状态(10)';
								button.intervaltext=button.textnode.innerHTML;
								var num=10;
								var that=this;
								button.input.disabled=true;
								button.input.style.opacity=0.6;
								this.value='';
								button.interval=setInterval(function(){
									num--;
									if(num>0){
										button.textnode.innerHTML='发状态('+num+')';
										button.intervaltext=button.textnode.innerHTML;
									}
									else{
										button.textnode.innerHTML='发状态';
										button.input.disabled=false;
										button.input.style.opacity='';
										clearInterval(button.interval);
										delete button.interval;
										delete button.intervaltext;
									}
								},1000);
							}
						}

						for(var i=0;i<button.info.length;i++){
							var node=ui.create.div('.menubutton.videonode.pointerdiv',uiintro.content);
							ui.create.div('.menubutton.videoavatar',node).setBackground(button.info[i][1]||'caocao','character');
							if(button.info[i][4]==game.wsid){
								ui.create.div('.name','<span class="thundertext thunderauto">'+(button.info[i][0]||'无名玩家'),node);node.isme=true;
							}
							else if(button.info[i][2]){
								ui.create.div('.name',(button.info[i][0]||'无名玩家'),node);
							}
							else{
								ui.create.div('.name','<span style="opacity:0.6">'+(button.info[i][0]||'无名玩家'),node);
							}
							//show ID
							//ui.create.div('.videostatus',node,button.info[i][5]);
							//node.classList.add('videonodestatus');
							if(button.info[i][3]){
								ui.create.div('.videostatus',node,button.info[i][3].slice(0,80));
								node.classList.add('videonodestatus')
							}
						}
					};

					uiintro.refresh();
					ui.window.appendChild(uiintro);
					_status.connectClientsCallback=function(){
						if(uiintro.parentNode==ui.window){
							uiintro.refresh();
						}
					};
				}
			},
			autoskin:function(){
				if(!lib.config.change_skin) return;
				var players=game.filterPlayer();
				var change=function(player,num,callback){
					if(num=='1'){
						ui.click.skin(player.node.avatar,player.name,callback);
					}
					else{
						ui.click.skin(player.node.avatar2,player.name2,callback);
					}
				};
				var finish=function(){
					if(lib.config.change_skin_auto!='off'){
						_status.skintimeout=setTimeout(ui.click.autoskin,parseInt(lib.config.change_skin_auto));
					}
				};
				var autoskin=function(){
					if(players.length){
						var player=players.randomRemove();
						var list=[];
						if(player.name&&!player.isUnseen(0)){
							list.push('1');
						}
						if(player.name2&&!player.isUnseen(1)){
							list.push('2');
						}
						if(list.length){
							change(player,list.randomRemove(),function(bool){
								if(bool){
									finish();
								}
								else if(list.length){
									change(player,list[0],function(bool){
										if(bool){
											finish();
										}
										else{
											autoskin();
										}
									});
								}
								else{
									autoskin();
								}
							});
						}
						else{
							autoskin();
						}
					}
				}
				autoskin();
			},
			skin:function(avatar,name,callback){
				var num=1;
				if(name.startsWith('gz_')){
					name=name.slice(3);
				}
				if(lib.config.skin[name]){
					num=lib.config.skin[name]+1;
				}
				var fakeavatar=avatar.cloneNode(true);
				var finish=function(bool){
					var player=avatar.parentNode;
					if(bool){
						fakeavatar.style.boxShadow='none';
						player.insertBefore(fakeavatar,avatar.nextSibling);
						setTimeout(function(){
							fakeavatar.delete();
						},100);
					}
					if(bool&&lib.config.animation&&!lib.config.low_performance){
						player.$rare();
					}
					if(callback){
						callback(bool);
					}
				}
				var img=new Image();
				img.onload=function(){
					lib.config.skin[name]=num;
					game.saveConfig('skin',lib.config.skin);
					avatar.style.backgroundImage='url("'+img.src+'")';
					finish(true);
				}
				img.onerror=function(){
					if(lib.config.skin[name]){
						finish(true);
					}
					else{
						finish(false);
					}
					delete lib.config.skin[name];
					game.saveConfig('skin',lib.config.skin);
					avatar.setBackground(name,'character');
				}
				img.src=lib.assetURL+'image/skin/'+name+'/'+num+'.jpg';
			},
			touchpop:function(forced){
				if(lib.config.touchscreen||forced){
					_status.touchpopping=true;
					clearTimeout(_status.touchpoppingtimeout);
					_status.touchpoppingtimeout=setTimeout(function(){
						_status.touchpopping=false;
					},600);
				}
			},
			exit:function(){
				if(game.servermode&&lib.config.reconnect_info&&_status.over){
					if(!_status.roomtimeout){
						lib.config.reconnect_info[2]=game.roomId;
						game.saveConfig('reconnect_info',lib.config.reconnect_info);
					}
					game.reload();
					return;
				}
				else{
					if(typeof game.roomId!='string'){
						game.saveConfig('reconnect_info');
					}
				}
				if(!ui.exit||!ui.exit.stay){
					if(lib.config.reconnect_info){
						lib.config.reconnect_info.length=1;
						game.saveConfig('reconnect_info',lib.config.reconnect_info);
					}
					game.saveConfig('tmp_user_roomId',undefined,false,function(){
						game.reload();
					});
				}
				else{
					game.reload();
				}
			},
			shortcut:function(show){
				if(show===false){
					ui.shortcut.classList.add('hidden');
				}
				else{
					ui.shortcut.classList.toggle('hidden');
				}
				if(ui.shortcut.classList.contains('hidden')){
					ui.favmode.style.display='none';
					if(window.StatusBar&&lib.config.show_statusbar_ios=='auto'){
						document.body.classList.remove('statusbar');
						window.StatusBar.hide();
					}
					ui.window.classList.remove('shortcutpaused');
				}
				else{
					if(lib.config.show_favmode){
						ui.favmode.style.display='';
					}
					if(window.StatusBar&&lib.config.show_statusbar_ios=='auto'){
						document.body.classList.add('statusbar');
						window.StatusBar.overlaysWebView(true);
						window.StatusBar.backgroundColorByName('black');
						window.StatusBar.show();
					}
					if(_status.auto){
						ui.shortcut.autobutton.classList.add('active');
					}
					else{
						ui.shortcut.autobutton.classList.remove('active');
					}
					ui.window.classList.add('shortcutpaused');
				}
			},
			favouriteCharacter:function(e){
				if(typeof this.link=='string'){
					if(this.innerHTML=='添加收藏'){
						this.innerHTML='移除收藏';
						lib.config.favouriteCharacter.add(this.link);
					}
					else{
						this.innerHTML='添加收藏';
						lib.config.favouriteCharacter.remove(this.link);
					}
					if(ui.favouriteCharacter){
						if(lib.config.favouriteCharacter.contains(this.link)){
							for(var i=0;i<ui.favouriteCharacter.childElementCount;i++){
								if(ui.favouriteCharacter.childNodes[i].link==this.link){
									break;
								}
							}
							if(i==ui.favouriteCharacter.childElementCount){
								ui.create.button(this.link,'character',ui.favouriteCharacter).listen(function(e){
									this._banning='offline';
									ui.click.touchpop();
									ui.click.intro.call(this,e);
									_status.clicked=false;
									delete this._banning;
								}).classList.add('noclick');
							}
						}
						else{
							for(var i=0;i<ui.favouriteCharacter.childElementCount;i++){
								if(ui.favouriteCharacter.childNodes[i].link==this.link){
									ui.favouriteCharacter.childNodes[i].remove();
									break;
								}
							}
						}
						var shownode=false;
						for(var i=0;i<lib.config.favouriteCharacter.length;i++){
							var favname=lib.config.favouriteCharacter[i];
							if(lib.character[favname]){
								shownode=true;break;
							}
						}
						if(shownode){
							ui.favouriteCharacter.node.style.display='';
						}
						else{
							ui.favouriteCharacter.node.style.display='none';
						}
					}
					game.saveConfig('favouriteCharacter',lib.config.favouriteCharacter);
				}
				e.stopPropagation();
			},
			buttonnameenter:function(){
				if(this.buttonscrollinterval){
					clearInterval(this.buttonscrollinterval);
				}
				var node=this.node.name;
				if(node.offsetHeight<node.scrollHeight){
					var that=this;
					var num=40;
					that.buttonscrollinterval=setInterval(function(){
						if(node.scrollTop+node.offsetHeight>=node.scrollHeight){
							clearInterval(that.buttonscrollinterval);
							delete that.buttonscrollinterval;
						}
						else{
							if(num>0){
								num--;
							}
							else{
								node.scrollTop+=2;
							}
						}
					},16);
				}
			},
			buttonnameleave:function(){
				if(this.buttonscrollinterval){
					clearInterval(this.buttonscrollinterval);
				}
				var node=this.node.name;
				if(node.offsetHeight<node.scrollHeight){
					var that=this;
					that.buttonscrollinterval=setInterval(function(){
						if(node.scrollTop==0){
							clearInterval(that.buttonscrollinterval);
							delete that.buttonscrollinterval;
						}
						else{
							node.scrollTop-=2;
						}
					},16);
				}
			},
			dragtouchdialog:function(e){
				if(e.touches.length>1&&
					!this.classList.contains('popped')&&
					!this.classList.contains('fixed')){
					_status.draggingtouchdialog=this;
					this._dragorigin={
						clientX:e.touches[0].clientX,
						clientY:e.touches[0].clientY,
					};
					if(!this._dragtransform){
						this._dragtransform=[0,0];
					}
					this._dragorigintransform=this._dragtransform.slice(0);
					e.preventDefault();
					e.stopPropagation();
				}
			},
			identity:function(e){
				if(_status.dragged) return;
				_status.clicked=true;
				if(!game.getIdentityList) return;
				if(_status.video) return;
				if(this.parentNode.forceShown) return;
				if(_status.clickingidentity){
					for(var i=0;i<_status.clickingidentity[1].length;i++){
						_status.clickingidentity[1][i].delete();
						_status.clickingidentity[1][i].style.transform='';
					}
					if(_status.clickingidentity[0]==this.parentNode){
						delete _status.clickingidentity;
						return;
					}
				}
				var list=game.getIdentityList(this.parentNode);
				if(!list) return;
				if(lib.config.mark_identity_style=='click'){
					var list2=[];
					for(var i in list){
						list2.push(i);
					}
					list2.push(list2[0]);
					for(var i=0;i<list2.length;i++){
						if(this.firstChild.innerHTML==list[list2[i]]){
							this.firstChild.innerHTML=list[list2[i+1]];
							this.dataset.color=list2[i+1];
							break;
						}
					}
				}
				else{
					if(get.mode()=='guozhan'){
						list={wei:'魏',shu:'蜀',wu:'吴',qun:'群',jin:'晋'};
						if(_status.forceKey) list.key='键';
					}
					var list2=get.copy(list);
					if(game.getIdentityList2){
						game.getIdentityList2(list2);
					}
					var rect=this.parentNode.getBoundingClientRect();
					this._customintro=function(uiintro){
						if(get.mode()=='guozhan'){
							uiintro.clickintro=true;
						}
						else{
							uiintro.touchclose=true;
						}
						// if(lib.config.theme!='woodden'){
						uiintro.classList.add('woodbg');
						// }
						if(get.is.phoneLayout()){
							uiintro.style.width='100px';
						}
						else{
							uiintro.style.width='85px';
						}
						var source=this.parentNode;
						for(var i in list){
							var node=ui.create.div();
							node.classList.add('guessidentity');
							node.classList.add('pointerdiv');
							ui.create.div('.menubutton.large',list2[i],node);
							if(!get.is.phoneLayout()){
								node.firstChild.style.fontSize='24px';
								node.firstChild.style.lineHeight='24px';
							}
							if(get.mode()=='guozhan'){
								if(source._guozhanguess){
									if(!source._guozhanguess.contains(i)){
										node.classList.add('transparent');
									}
								}
								node._source=source;
								node.listen(ui.click.identitycircle);
							}
							else{
								node.listen(function(){
									var info=this.link;
									info[0].firstChild.innerHTML=info[1];
									info[0].dataset.color=info[2];
									_status.clicked=false;
								});
							}

							node.link=[this,list[i],i];
							uiintro.add(node);
						}
					};
					ui.click.touchpop();
					ui.click.intro.call(this,{
						clientX:(rect.left+rect.width),
						clientY:(rect.top)
					});
					// var nodes=[];
					// _status.clickingidentity=[this.parentNode,nodes];
					// var num=1;
					// var dy=30;
					// if(get.is.phoneLayout()){
					// 	dy=45;
					// }
					// for(var i in list){
					// 	if(this.firstChild.innerHTML!=list[i]){
					// 		var node=ui.create.div('.identity.hidden.pointerdiv',this.parentNode,ui.click.identity2);
					// 		ui.create.div(node).innerHTML=list[i];
					// 		node.dataset.color=i;
					// 		ui.refresh(node);
					// 		node.show();
					// 		var transstr='translateY('+((num++)*dy)+'px)';
					// 		if(get.is.phoneLayout()){
					// 			transstr+=' scale(1.3)';
					// 		}
					// 		if(get.is.newLayout()&&this.parentNode.classList.contains('linked')){
					// 			transstr+=' rotate(90deg)';
					// 		}
					// 		node.style.transform=transstr;
					// 		nodes.push(node);
					// 	}
					// }
				}
			},
			identity2:function(){
				if(_status.clickingidentity){
					_status.clicked=true;
					var player=_status.clickingidentity[0];
					var nodes=_status.clickingidentity[1];
					player.node.identity.dataset.color=this.dataset.color;
					player.node.identity.firstChild.innerHTML=this.firstChild.innerHTML;
					for(var i=0;i<nodes.length;i++){
						nodes[i].delete();
						nodes[i].style.transform='';
					}
					delete _status.clickingidentity;
				}
			},
			roundmenu:function(){
				game.closeConnectMenu();
				switch(lib.config.round_menu_func){
					case 'system':
						game.closePopped();
						ui.system1.classList.add('shown');
						ui.system2.classList.add('shown');
						game.closeMenu();
						ui.click.shortcut();
						break;
					case 'menu':
						if(ui.click.configMenu){
							game.closePopped();
							game.pause2();
							ui.click.configMenu();
							ui.system1.classList.remove('shown');
							ui.system2.classList.remove('shown');
						}
						break;
					case 'pause':
						ui.click.pause();
						break;
					case 'auto':
						ui.click.auto();
						break;
				}
				_status.clicked=true;
			},
			pausehistory:function(){
				if(!lib.config.auto_popped_history) return;
				if(!ui.sidebar.childNodes.length) return;
				var uiintro=ui.create.dialog('hidden');
				uiintro.style.maxHeight='400px';
				uiintro.add(ui.sidebar);
				return uiintro;
			},
			pauseconfig:function(){
				if(!lib.config.auto_popped_config) return;
				if(get.is.phoneLayout()) return;
				var uiintro=ui.create.dialog('hidden');
				uiintro.listen(function(e){
					e.stopPropagation();
				});

				var rows=Math.floor(lib.config.all.mode.length/3);
				uiintro.type='config';
				var modes=lib.config.modeorder||lib.config.all.mode.slice(0);
				for(var i=0;i<modes.length;i++){
					if(!lib.config.all.mode.contains(modes[i])){
						modes.splice(i--,1);
					}
				}
				for(var k=0;k<rows;k++){
					var node=ui.create.div('.newgame.pointernode');
					for(var i=0;i<3&&i+k*3<modes.length;i++){
						var thismode=modes[i+k*3];
						var div=ui.create.div(thismode==(_status.sourcemode||lib.config.mode)?'.underlinenode.on':'.underlinenode',node);
						div.innerHTML=lib.translate[thismode];
						div.link=thismode;
						div.addEventListener(lib.config.touchscreen?'touchend':'click',function(){
							game.saveConfig('mode',this.link);
							localStorage.setItem(lib.configprefix+'directstart',true);
							game.reload();
						});
					}
					uiintro.add(node);
				}

				return uiintro;
			},
			cardPileButton:function(){
				var uiintro=ui.create.dialog('hidden');
				uiintro.listen(function(e){
					e.stopPropagation();
				});
				var num;
				if(game.online){
					num=_status.cardPileNum||0;
				}
				else{
					num=ui.cardPile.childNodes.length;
				}
				uiintro.add('剩余 <span style="font-family:'+'xinwei'+'">'+num);

				if(_status.connectMode) return uiintro;
				uiintro.add('<div class="text center">轮数 <span style="font-family:xinwei">'+game.roundNumber+'</span>&nbsp;&nbsp;&nbsp;&nbsp;洗牌 <span style="font-family:xinwei">'+game.shuffleNumber+'</div>');
				uiintro.add('<div class="text center">弃牌堆</div>');
				if(ui.discardPile.childNodes.length){
					var list=[];
					for(var i=0;i<ui.discardPile.childNodes.length;i++){
						list.unshift(ui.discardPile.childNodes[i]);
					}
					uiintro.addSmall([list,'card']);
				}
				else{
					uiintro.add('<div class="text center" style="padding-bottom:3px">无</div>');
				}
				return uiintro;
			},
			chat:function(){
				ui.system1.classList.add('shown');
				ui.system2.classList.add('shown');

				var uiintro=ui.create.dialog('hidden');
				uiintro.listen(function(e){
					e.stopPropagation();
				});

				var list=ui.create.div('.caption');
				if(get.is.phoneLayout()){
					list.style.maxHeight='110px';
				}
				else{
					list.style.maxHeight='220px';
				}
				list.style.overflow='scroll';
				lib.setScroll(list);
				uiintro.contentContainer.style.overflow='hidden';

				var input;
				var addEntry=function(info,clear){
					if(list._chatempty){
						list.innerHTML='';
						delete list._chatempty;
					}
					var node=ui.create.div('.text.chat');
					node.innerHTML=info[0]+': '+info[1];
					list.appendChild(node);
					list.scrollTop=list.scrollHeight;
					uiintro.style.height=uiintro.content.scrollHeight+'px';
				}
				_status.addChatEntry=addEntry;
				_status.addChatEntry._origin=uiintro;
				if(lib.chatHistory.length){
					for(var i=0;i<lib.chatHistory.length;i++){
						addEntry(lib.chatHistory[i]);
					}
				}
				else{
					list._chatempty=true;
					list.appendChild(ui.create.div('.text.center','无聊天记录'))
				}
				uiintro.add(list);
				uiintro.style.height=uiintro.content.offsetHeight+'px';
				list.scrollTop=list.scrollHeight;

				if(!_status.chatValue) _status.chatValue='';
				var node=uiintro.add('<input type="text" value="'+_status.chatValue+'">');
				node.style.paddingTop=0;
				node.style.marginBottom='16px';
				input=node.firstChild;
				input.style.width='calc(100% - 20px)';
				input.onchange=function(){
					_status.chatValue=input.value;
				}
				input.onkeydown=function(e){
					if(e.keyCode==13&&input.value){
						var player=game.me;
						var str=input.value;
						if(!player){
							if(game.connectPlayers){
								if(game.online){
									for(var i=0;i<game.connectPlayers.length;i++){
										if(game.connectPlayers[i].playerid==game.onlineID){
											player=game.connectPlayers[i];break;
										}
									}
								}
								else{
									player=game.connectPlayers[0];
								}
							}
						}
						if(!player) return;
						if(get.is.banWords(input.value)){
							player.say(input.value);
							input.value='';
							_status.chatValue='';
						}
						else{
							if(game.online){
								game.send('chat',game.onlineID,str);
							}
							else{
								lib.element.player.chat.call(player,str);
							}
							input.value='';
							_status.chatValue='';
						}
					}
					e.stopPropagation();
				}
				uiintro._onopen=function(){
					input.focus();
					list.scrollTop=list.scrollHeight;
				};
				uiintro._heightfixed=true;
				var emotionTitle=ui.create.div('.text.center','聊天表情',function(){
					if(emotionTitle.innerHTML=='快捷语音'){
						emotionTitle.innerHTML='聊天表情';
						list2.remove();
						list3.remove();
						uiintro.add(list1);
						while(list2.childNodes.length){
							list2.firstChild.remove();
						}
					}
					else{
						emotionTitle.innerHTML='快捷语音';
						list1.remove();
						list2.remove();
						uiintro.add(list3);
					}
				});
				uiintro.add(emotionTitle);
				var list1=ui.create.div('');
				if(get.is.phoneLayout()){
					list1.style.height='110px';
				}
				else{
					list1.style.height='150px';
				}
				list1.style.overflow='scroll';
				lib.setScroll(list1);
				uiintro.add(list1);
				uiintro.style.height=uiintro.content.scrollHeight+'px';
				var list2=ui.create.div('');
				if(get.is.phoneLayout()){
					list2.style.height='110px';
				}
				else{
					list2.style.height='150px';
				}
				list2.style.overflow='scroll';
				lib.setScroll(list2);
				//uiintro.add(list2);
				for(var i in lib.emotionList){
					var emotionPack=ui.create.div('.card.fullskin','<img src="'+lib.assetURL+'image/emotion/'+i+'/1.gif" width="50" height="50">',function(){
						emotionTitle.innerHTML=get.translation(this.pack);
						for(var j=1;j<=lib.emotionList[this.pack];j++){
							var emotionButton=ui.create.div('.card.fullskin','<img src="'+lib.assetURL+'image/emotion/'+this.pack+'/'+j+'.gif" width="50" height="50">',function(){
								var player=game.me;
								if(!player){
									if(game.connectPlayers){
										if(game.online){
											for(var i=0;i<game.connectPlayers.length;i++){
												if(game.connectPlayers[i].playerid==game.onlineID){
													player=game.connectPlayers[i];break;
												}
											}
										}
										else{
											player=game.connectPlayers[0];
										}
									}
								}
								if(!player) return;
								if(game.online){
									game.send('emotion',game.onlineID,this.pack,this.emotionID);
								}
								else{
									lib.element.player.emotion.apply(player,[this.pack,this.emotionID]);
								}
							});
							emotionButton.emotionID=j;
							emotionButton.pack=this.pack;
							emotionButton.style.height='50px';
							emotionButton.style.width='50px';
							list2.appendChild(emotionButton);
						}
						list1.remove();
						uiintro.add(list2);
					});
					emotionPack.pack=i;
					emotionPack.style.height='50px';
					emotionPack.style.width='50px';
					list1.appendChild(emotionPack);
				}
				list1.scrollTop=list1.scrollHeight;
				uiintro.style.height=uiintro.content.scrollHeight+'px';
				var list3=ui.create.div('.caption');
				if(get.is.phoneLayout()){
					list3.style.height='110px';
				}
				else{
					list3.style.height='150px';
				}
				list3.style.overflow='scroll';
				lib.setScroll(list3);
				for(var i=0;i<lib.quickVoice.length;i++){
					var node=ui.create.div('.text.chat',function(){
						var player=game.me;
						var str=this.innerHTML;
						if(!player){
							if(game.connectPlayers){
								if(game.online){
									for(var i=0;i<game.connectPlayers.length;i++){
										if(game.connectPlayers[i].playerid==game.onlineID){
											player=game.connectPlayers[i];break;
										}
									}
								}
								else{
									player=game.connectPlayers[0];
								}
							}
						}
						if(!player) return;
						if(game.online){
							game.send('chat',game.onlineID,str);
						}
						else{
							lib.element.player.chat.call(player,str);
						}
					});
					node.innerHTML=lib.quickVoice[i];
					list3.appendChild(node);
				}
				list3.scrollTop=list1.scrollHeight;
				return uiintro;
			},
			volumn:function(){
				var uiintro=ui.create.dialog('hidden');
				uiintro.listen(function(e){
					e.stopPropagation();
				});
				uiintro.add('背景音乐');
				var vol1=ui.create.div('.volumn');
				uiintro.add(vol1);
				for(var i=0;i<8;i++){
					var span=document.createElement('span');
					span.link=i+1;
					span.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.volumn_background);
					if(i<lib.config.volumn_background){
						span.innerHTML='●';
					}
					else{
						span.innerHTML='○';
					}
					vol1.appendChild(span);
				}
				uiintro.add('游戏音效');

				var vol2=ui.create.div('.volumn');
				uiintro.add(vol2);
				for(var i=0;i<8;i++){
					var span=document.createElement('span');
					span.link=i+1;
					span.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.volumn_audio);
					if(i<lib.config.volumn_audio){
						span.innerHTML='●';
					}
					else{
						span.innerHTML='○';
					}
					vol2.appendChild(span);
				}
				uiintro.add(ui.create.div('.placeholder'));
				return uiintro;
			},
			volumn_background:function(e){
				if(_status.dragged) return;
				var volume=this.link;
				if(volume===1&&lib.config.volumn_background===1){
					volume=0;
				}
				game.saveConfig('volumn_background',volume);
				ui.backgroundMusic.volume=volume/8;
				for(var i=0;i<8;i++){
					if(i<lib.config.volumn_background){
						this.parentNode.childNodes[i].innerHTML='●';
					}
					else{
						this.parentNode.childNodes[i].innerHTML='○';
					}
				}
				e.stopPropagation();
			},
			volumn_audio:function(e){
				if(_status.dragged) return;
				var volume=this.link;
				if(volume===1&&lib.config.volumn_audio===1){
					volume=0;
				}
				game.saveConfig('volumn_audio',volume);
				for(var i=0;i<8;i++){
					if(i<lib.config.volumn_audio){
						this.parentNode.childNodes[i].innerHTML='●';
					}
					else{
						this.parentNode.childNodes[i].innerHTML='○';
					}
				}
				e.stopPropagation();
			},
			hoverpopped:function(){
				if(this._uiintro){
					return;
				}
				if(!this._poppedfunc){
					return;
				}
				ui.click.touchpop(this.forceclick);
				var uiintro=this._poppedfunc();
				if(!uiintro) return;
				if(ui.currentpopped&&ui.currentpopped._uiintro){
					ui.currentpopped._uiintro.delete();
					delete ui.currentpopped._uiintro;
				}
				ui.currentpopped=this;
				uiintro.classList.add('popped');
				uiintro.classList.add('hoverdialog');
				uiintro.classList.add('static');
				this._uiintro=uiintro;

				ui.window.appendChild(uiintro);
				var width=this._poppedwidth||330;
				uiintro.style.width=width+'px';
				if(get.is.phoneLayout()){
					width*=1.3;
				}

				if(uiintro._heightfixed){
					uiintro.style.height=uiintro.content.scrollHeight+'px';
				}
				else{
					var height=this._poppedheight||uiintro.content.scrollHeight;
					var height2=ui.window.offsetHeight-260;
					if(get.is.phoneLayout()){
						height2=(ui.window.offsetHeight-80)/1.3;
					}
					uiintro.style.height=Math.min(height2,height)+'px';
				}
				if(get.is.phoneLayout()){
					uiintro.style.top='70px';
				}
				else{
					uiintro.style.top='50px';
				}
				var left=this.parentNode.offsetLeft+this.offsetLeft+this.offsetWidth/2-width/2;
				if(left<10){
					left=10;
				}
				else if(left+width>ui.window.offsetWidth-10){
					left=ui.window.offsetWidth-width-10;
				}
				uiintro.style.left=left+'px';
				uiintro._poppedorigin=this;
				if(!lib.config.touchscreen){
					uiintro.addEventListener('mouseleave',ui.click.leavehoverpopped);
				}
				ui.click.shortcut(false);
				if(uiintro._onopen){
					uiintro._onopen();
				}
				if(this._paused2&&!lib.config.touchscreen){
					game.pause2();
					uiintro.classList.add('static');
					var layer=ui.create.div('.poplayer',ui.window);
					var clicklayer=function(e){
						uiintro.delete();
						layer.remove();
						game.resume2();
						e.stopPropagation();
						return false;
					}
					uiintro.style.zIndex=21;
					layer.onclick=clicklayer;
					layer.oncontextmenu=clicklayer;
					uiintro.addEventListener('mouseleave',clicklayer);
					uiintro.addEventListener('click',clicklayer);
				}
			},
			hoverpopped_leave:function(){
				this._poppedalready=false;
			},
			leavehoverpopped:function(){
				if(_status.dragged) return;
				if(this.classList.contains('noleave')) return;
				this.delete();
				var button=this._poppedorigin;

				var uiintro=this;
				setTimeout(function(){
					if(button._uiintro==uiintro){
						delete button._uiintro;
					}
				},500);

			},
			dierevive:function(){
				if(game.me.isDead()){
					game.me.revive(Math.max(1,game.me.maxHp));
					game.me.draw(2);
				}
				else{
					if(ui.revive){
						ui.revive.close();
						delete ui.revive;
					}
				}
			},
			dieswap:function(){
				if(game.me.isDead()){
					_status.clicked=true;
					var i,translation,intro,str;
					if(ui.intro){
						ui.intro.close();
						if(ui.intro.source=='dieswap'){
							delete ui.intro;
							ui.control.show();
							game.resume2();
							return;
						}
					}
					game.pause2();
					ui.control.hide();
					ui.intro=ui.create.dialog();
					ui.intro.source='dieswap';

					var players=[];
					for(var i=0;i<game.players.length;i++){
						if(game.players[i].isAlive()){
							players.push(game.players[i]);
						}
					}
					ui.intro.add(players,true);
					var buttons=ui.intro.querySelectorAll('.button');
					for(var i=0;i<buttons.length;i++){
						buttons[i].addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.dieswap2);
					}
				}
				else{
					if(ui.swap){
						ui.swap.close();
						delete ui.swap;
					}
				}
			},
			dieswap2:function(){
				if(_status.dragged) return;
				game.swapPlayer(this.link);
			},
			touchconfirm:function(){
				_status.touchconfirmed=true;
				document.removeEventListener('touchstart',ui.click.touchconfirm);
			},
			windowtouchstart:function(e){
				if(window.inSplash) return;
				if(e.touches[0]&&lib.config.swipe&&e.touches.length<2){
					_status._swipeorigin={
						clientX:e.touches[0].clientX,
						clientY:e.touches[0].clientY,
						time:get.utc()
					}
				}
				// if(window.ForceTouch&&!_status.paused2&&!_status.forcetouchinterval&&lib.config.enable_pressure){
				// 	_status.forcetouchinterval=setInterval(ui.click.forcetouch,30);
				// }
			},
			windowtouchmove:function(e){
				e.preventDefault();
				if(window.inSplash) return;
				if(_status.draggingroundmenu){
					delete _status._swipeorigin;
					if(ui.roundmenu._dragorigin&&ui.roundmenu._dragtransform&&e.touches.length){
						var translate=ui.roundmenu._dragtransform.slice(0);
						var dx=e.touches[0].clientX/game.documentZoom-ui.roundmenu._dragorigin.clientX/game.documentZoom;
						var dy=e.touches[0].clientY/game.documentZoom-ui.roundmenu._dragorigin.clientY/game.documentZoom;
						translate[0]+=dx;
						translate[1]+=dy;
						if(dx*dx+dy*dy>100){
							if(ui.roundmenu._resetTimeout){
								clearTimeout(ui.roundmenu._resetTimeout);
								delete ui.roundmenu._resetTimeout;
							}
						}
						ui.roundmenu._dragtouches=e.touches[0];
						ui.click.checkroundtranslate(translate);
					}
					_status.clicked=true;
				}
				else if(_status.draggingtouchdialog){
					delete _status._swipeorigin;
					if(_status.draggingtouchdialog._dragorigin&&_status.draggingtouchdialog._dragtransform&&e.touches.length){
						var translate=_status.draggingtouchdialog._dragtransform.slice(0);
						var dx=e.touches[0].clientX/game.documentZoom-_status.draggingtouchdialog._dragorigin.clientX/game.documentZoom;
						var dy=e.touches[0].clientY/game.documentZoom-_status.draggingtouchdialog._dragorigin.clientY/game.documentZoom;
						translate[0]+=dx;
						translate[1]+=dy;
						_status.draggingtouchdialog._dragtouches=e.touches[0];
						ui.click.checkdialogtranslate(translate,_status.draggingtouchdialog);
					}
					_status.clicked=true;
				}
				else if(_status._swipeorigin&&e.touches[0]){
					_status._swipeorigin.touches=e.touches[0];
				}

				if(_status.mousedragging&&e.touches.length){
					e.preventDefault();
					var item=document.elementFromPoint(e.touches[0].clientX,e.touches[0].clientY);
					if(game.chess&&ui.selected.cards.length){
						var itemtype=get.itemtype(item);
						if(itemtype!='card'&&itemtype!='button'){
							var ex=e.touches[0].clientX/game.documentZoom-ui.arena.offsetLeft;
							var ey=e.touches[0].clientY/game.documentZoom-ui.arena.offsetTop;
							for(var i=0;i<game.players.length;i++){
								var left=-ui.chessContainer.chessLeft+ui.chess.offsetLeft+game.players[i].getLeft();
								var top=-ui.chessContainer.chessTop+ui.chess.offsetTop+game.players[i].getTop();
								var width=game.players[i].offsetWidth;
								var height=game.players[i].offsetHeight;
								if(ex>left&&ex<left+width&&ey>top&&ey<top+height){
									item=game.players[i];
									break;
								}
							}
						}
					}
					while(item){
						if(lib.config.enable_touchdragline&&_status.mouseleft&&!game.chess){
							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.lineWidth=3;
							ctx.setLineDash([8,2]);

							ctx.beginPath();

							ctx.moveTo(_status.mousedragging.clientX/game.documentZoom-ui.arena.offsetLeft,_status.mousedragging.clientY/game.documentZoom-ui.arena.offsetTop);

							if(_status.multitarget){
								for(var i=0;i<_status.lastdragchange.length;i++){
									var exy=_status.lastdragchange[i]._lastdragchange;
									ctx.lineTo(exy[0],exy[1]);
								}
							}
							if(!_status.selectionfull){
								ctx.lineTo(e.touches[0].clientX/game.documentZoom-ui.arena.offsetLeft,e.touches[0].clientY/game.documentZoom-ui.arena.offsetTop);
							}
							ctx.stroke();
							if(!_status.multitarget){
								for(var i=0;i<_status.lastdragchange.length;i++){
									ctx.moveTo(_status.mousedragging.clientX/game.documentZoom-ui.arena.offsetLeft,_status.mousedragging.clientY/game.documentZoom-ui.arena.offsetTop);
									var exy=_status.lastdragchange[i]._lastdragchange;
									ctx.lineTo(exy[0],exy[1]);
									ctx.stroke();
								}
							}
						}

						if(item==_status.mousedragorigin){
							if(_status.mouseleft){
								_status.mousedragging=null;
								_status.mousedragorigin=null;
								_status.clicked=false;
								game.uncheck();
								game.check();
								_status.clicked=true;
							}
							return;
						}
						var itemtype=get.itemtype(item);
						if(itemtype=='card'||itemtype=='button'||itemtype=='player'){
							_status.mouseleft=true;
							if(ui.selected.cards.length){
								ui.selected.cards[0].updateTransform(true,100);
							}
							var ex=e.touches[0].clientX/game.documentZoom-ui.arena.offsetLeft;
							var ey=e.touches[0].clientY/game.documentZoom-ui.arena.offsetTop;
							var exx=ex,eyy=ey;
							if(game.chess){
								ex-=-ui.chessContainer.chessLeft+ui.chess.offsetLeft;
								ey-=-ui.chessContainer.chessTop+ui.chess.offsetTop;
							}
							if(itemtype!='player'||game.chess||(ex>item.offsetLeft&&ex<item.offsetLeft+item.offsetWidth&&
								ey>item.offsetTop&&ey<item.offsetTop+item.offsetHeight)){
								var targetfixed=false;
								if(itemtype=='player'){
									if(get.select(_status.event.selectTarget)[1]<=-1){
										targetfixed=true;
									}
								}
								if(!targetfixed&&item.classList.contains('selectable')&&_status.dragstatuschanged!=item){
									_status.mouseleft=true;
									_status.dragstatuschanged=item;
									_status.clicked=false;
									_status.dragged=false;
									var notbefore=itemtype=='player'&&!item.classList.contains('selected');
									ui.click[itemtype].call(item);
									if(item.classList.contains('selected')){
										if(notbefore){
											_status.lastdragchange.push(item);
											item._lastdragchange=[exx,eyy];
											if(lib.falseitem){
												var from=[_status.mousedragging.clientX/game.documentZoom-ui.arena.offsetLeft,_status.mousedragging.clientY/game.documentZoom-ui.arena.offsetTop];
												var to=[exx,eyy];
												var node=ui.create.div('.linexy.hidden');
												node.style.left=from[0]+'px';
												node.style.top=from[1]+'px';
												node.style.transitionDuration='0.3s';
												node.style.backgroundColor='white';
												var dy=to[1]-from[1];
												var dx=to[0]-from[0];
												var deg=Math.atan(Math.abs(dy)/Math.abs(dx))/Math.PI*180;
												if(dx>=0){
													if(dy<=0){
														deg+=90;
													}
													else{
														deg=90-deg;
													}
												}
												else{
													if(dy<=0){
														deg=270-deg;
													}
													else{
														deg+=270;
													}
												}
												node.style.transform='rotate('+(-deg)+'deg) scaleY(0)';
												node.style.height=get.xyDistance(from,to)+'px';
												if(game.chess){
													ui.chess.appendChild(node);
												}
												else{
													ui.arena.appendChild(node);
												}
												ui.refresh(node);
												node.show();
												node.style.transform='rotate('+(-deg)+'deg) scaleY(1)';
												ui.touchlines.push(node);
												node._origin=item;
											}
										}
									}
									else{
										_status.lastdragchange.remove(item);
										for(var i=0;i<ui.touchlines.length;i++){
											if(ui.touchlines[i]._origin==item){
												ui.touchlines[i].delete();
												ui.touchlines.splice(i--,1);
											}
										}
									}
									_status.selectionfull=true;
									if(_status.event.filterButton&&ui.selected.buttons.length<get.select(_status.event.selectButton)[1]){
										_status.selectionfull=false;
									}
									else if(_status.event.filterCard&&ui.selected.cards.length<get.select(_status.event.selectCard)[1]){
										_status.selectionfull=false;
									}
									else if(_status.event.filterTarget&&ui.selected.targets.length<get.select(_status.event.selectTarget)[1]){
										_status.selectionfull=false;
									}
								}
							}
							return;
						}
						item=item.parentNode;
					}
					_status.mouseleft=true;
					_status.dragstatuschanged=null;
				}
			},
			windowtouchend:function(e){
				delete _status.force;
				// if(_status.forcetouchinterval){
				// 	clearInterval(_status.forcetouchinterval);
				// 	delete _status.forcetouchinterval;
				// }
				if(window.inSplash) return;
				if(e.touches.length==1&&!_status.dragged&&!_status.draggingtouchdialog){
					ui.click.pause();
				}
				if(_status.draggingroundmenu){
					delete _status._swipeorigin;
					if(ui.roundmenu._resetTimeout){
						clearTimeout(ui.roundmenu._resetTimeout);
						delete ui.roundmenu._resetTimeout;
					}
					var translate;
					if(ui.roundmenu._dragorigin&&ui.roundmenu._dragtransform&&ui.roundmenu._dragtouches){
						var dx=ui.roundmenu._dragtouches.clientX/game.documentZoom-ui.roundmenu._dragorigin.clientX/game.documentZoom;
						var dy=ui.roundmenu._dragtouches.clientY/game.documentZoom-ui.roundmenu._dragorigin.clientY/game.documentZoom;
						if(dx*dx+dy*dy<1000){
							ui.click.roundmenu();
							ui.roundmenu._dragtransform=ui.roundmenu._dragorigintransform;
							translate=ui.roundmenu._dragtransform;
							ui.roundmenu.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)';
						}
						else{
							translate=ui.roundmenu._dragtransform;
							translate[0]+=dx;
							translate[1]+=dy;
							ui.click.checkroundtranslate();
						}
						delete ui.roundmenu._dragorigin;
					}
					else{
						ui.click.roundmenu();
					}
					_status.clicked=false;
					game.saveConfig('roundmenu_transform',translate);
					delete _status.draggingroundmenu;
				}
				else if(_status.draggingtouchdialog){
					delete _status._swipeorigin;
					var translate;
					if(_status.draggingtouchdialog._dragorigin&&_status.draggingtouchdialog._dragtransform&&_status.draggingtouchdialog._dragtouches){
						var dx=_status.draggingtouchdialog._dragtouches.clientX/game.documentZoom-_status.draggingtouchdialog._dragorigin.clientX/game.documentZoom;
						var dy=_status.draggingtouchdialog._dragtouches.clientY/game.documentZoom-_status.draggingtouchdialog._dragorigin.clientY/game.documentZoom;
						translate=_status.draggingtouchdialog._dragtransform;
						translate[0]+=dx;
						translate[1]+=dy;
						ui.click.checkdialogtranslate(null,_status.draggingtouchdialog);

						delete _status.draggingtouchdialog._dragorigin;
					}
					_status.clicked=false;
					game.saveConfig('dialog_transform',translate);
					delete _status.draggingtouchdialog;
					_status.justdragged=true;
					setTimeout(function(){
						_status.justdragged=false;
					},500);
				}
				else if(_status._swipeorigin&&!_status.paused2&&!_status.mousedragging&&_status._swipeorigin.touches&&!_status.filterCharacter){
					if(get.utc()-_status._swipeorigin.time<500){
						var dx=_status._swipeorigin.touches.clientX/game.documentZoom-_status._swipeorigin.clientX/game.documentZoom;
						var dy=_status._swipeorigin.touches.clientY/game.documentZoom-_status._swipeorigin.clientY/game.documentZoom;
						var goswipe=function(action){
							game.closeConnectMenu();
							switch(action){
								case 'system':
									game.closePopped();
									ui.system1.classList.add('shown');
									ui.system2.classList.add('shown');
									game.closeMenu();
									ui.click.shortcut();
									break;
								case 'menu':
									if(ui.click.configMenu){
										game.closePopped();
										game.pause2();
										ui.click.configMenu();
										ui.system1.classList.remove('shown');
										ui.system2.classList.remove('shown');
									}
									break;
								case 'pause':
									ui.click.pause();
									break;
								case 'auto':
									ui.click.auto();
									break;
								case 'chat':
									game.closeMenu();
									if(ui.chatButton){
										ui.click.hoverpopped.call(ui.chatButton);
									}
									break;
							}
						}
						if(Math.abs(dx)<100){
							if(dy<-200){
								goswipe(lib.config.swipe_up);
							}
							else if(dy>200){
								goswipe(lib.config.swipe_down);
							}
						}
						else if(Math.abs(dy)<100){
							if(dx<-200){
								goswipe(lib.config.swipe_left);
							}
							else if(dx>200){
								goswipe(lib.config.swipe_right);
							}
						}
					}
				}
				var tmpflag=false;
				_status.mousedown=false;
				_status.clicked=false;
				if(_status.mousedragging&&_status.mouseleft){
					if(game.check()){
						if(ui.confirm){
							ui.confirm.close();
						}
						var event=_status.event;
						if(!event.filterOk||event.filterOk()) ui.click.ok();
						ui.canvas.width=ui.arena.offsetWidth;
						ui.canvas.height=ui.arena.offsetHeight;
					}
					else{
						game.uncheck();
						game.check();
					}
				}
				else if(_status.mousedragging&&_status.mousedragorigin){
					tmpflag=_status.mousedragorigin;
				}
				_status.lastdragchange.length=0;
				_status.mousedragging=null;
				_status.mouseleft=false;
				_status.mousedragorigin=null;
				_status.dragstatuschanged=false;
				while(ui.touchlines.length){
					ui.touchlines.shift().delete();
				}
				if(tmpflag){
					game.check();
				}
				_status.dragged=false;
				_status.clicked=false;
			},
			checkroundtranslate:function(translate){
				var translate=translate||ui.roundmenu._dragtransform;
				if(translate[1]+ui.roundmenu._position[1]+50+ui.arena.offsetTop>ui.window.offsetHeight){
					translate[1]=ui.window.offsetHeight-(ui.roundmenu._position[1]+50)-ui.arena.offsetTop;
				}
				else if(translate[1]+ui.roundmenu._position[1]+ui.arena.offsetTop<0){
					translate[1]=-ui.roundmenu._position[1]-ui.arena.offsetTop;
				}
				if(translate[0]+ui.roundmenu._position[0]+50+ui.arena.offsetLeft>ui.window.offsetWidth){
					translate[0]=ui.window.offsetWidth-(ui.roundmenu._position[0]+50)-ui.arena.offsetLeft;
				}
				else if(translate[0]+ui.roundmenu._position[0]+ui.arena.offsetLeft<0){
					translate[0]=-ui.roundmenu._position[0]-ui.arena.offsetLeft;
				}
				ui.roundmenu.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)';
			},
			checkdialogtranslate:function(translate,dialog){
				var translate=translate||dialog._dragtransform;
				if(Math.sqrt(translate[0]*translate[0]+translate[1]*translate[1])<10){
					translate[0]=0;
					translate[1]=0;
				}
				dialog.style.transform='translate('+translate[0]+'px,'+translate[1]+'px)';
			},
			windowmousewheel:function(e){
				_status.tempunpopup=e;
			},
			windowmousemove:function(e){
				if(window.inSplash) return;
				if(_status.tempunpopup){
					if(get.evtDistance(_status.tempunpopup,e)>5){
						delete _status.tempunpopup;
					}
				}
				if(e.button==2) return;
				var dialogs=document.querySelectorAll('#window>.dialog.popped:not(.static)');
				for(var i=0;i<dialogs.length;i++){
					dialogs[i].delete();
				}
				var node=_status.currentmouseenter;
				var sourceitem=document.elementFromPoint(e.clientX,e.clientY);
				if(game.chess&&ui.selected.cards.length){
					var itemtype=get.itemtype(sourceitem);
					if(itemtype!='card'&&itemtype!='button'){
						for(var i=0;i<game.players.length;i++){
							var ex=e.clientX/game.documentZoom-ui.arena.offsetLeft;
							var ey=e.clientY/game.documentZoom-ui.arena.offsetTop;
							var left=-ui.chessContainer.chessLeft+ui.chess.offsetLeft+game.players[i].getLeft();
							var top=-ui.chessContainer.chessTop+ui.chess.offsetTop+game.players[i].getTop();
							var width=game.players[i].offsetWidth;
							var height=game.players[i].offsetHeight;
							if(ex>left&&ex<left+width&&ey>top&&ey<top+height){
								sourceitem=game.players[i];
								break;
							}
						}
					}
				}
				var item=sourceitem;
				if(_status.mousedragging){
					e.preventDefault();
					if(lib.config.enable_dragline){
						// var i=0;
						// var startPoint0=[_status.mousedragging.clientX/game.documentZoom-ui.arena.offsetLeft,_status.mousedragging.clientY/game.documentZoom-ui.arena.offsetTop];
						// var startPoint=startPoint0;
						// var endPoint;
						// if(_status.multitarget){
						// 	for(;i<_status.lastdragchange.length;i++){
						// 		var exy=_status.lastdragchange[i]._lastdragchange;
						// 		endPoint=[exy[0],exy[1]];
						// 		_status.dragline[i]=game.linexy(startPoint.concat(endPoint),'drag',_status.dragline[i]);
						// 		startPoint=endPoint;
						// 	}
						// }
						// if(!_status.selectionfull){
						// 	endPoint=[e.clientX/game.documentZoom-ui.arena.offsetLeft,e.clientY/game.documentZoom-ui.arena.offsetTop];
						// 	_status.dragline[i]=game.linexy(startPoint.concat(endPoint),'drag',_status.dragline[i]);
						// 	startPoint=endPoint;
						// 	i++;
						// }
						// if(!_status.multitarget){
						// 	for(var j=0;j<_status.lastdragchange.length;j++){
						// 		i+=j;
						// 		var exy=_status.lastdragchange[j]._lastdragchange;
						// 		_status.dragline[i]=game.linexy(startPoint0.concat([exy[0],exy[1]]),'drag',_status.dragline[i]);
						// 	}
						// }
						// var remained=_status.dragline.splice(i+1);
						// for(var j=0;j<remained.length;j++){
						// 	if(remained[j]) remained[j].remove();
						// }

						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.lineWidth=3;
						ctx.setLineDash([8,2]);

						ctx.beginPath();

						ctx.moveTo(_status.mousedragging.clientX/game.documentZoom-ui.arena.offsetLeft,_status.mousedragging.clientY/game.documentZoom-ui.arena.offsetTop);
						if(_status.multitarget){
							for(var i=0;i<_status.lastdragchange.length;i++){
								var exy=_status.lastdragchange[i]._lastdragchange;
								ctx.lineTo(exy[0],exy[1]);
							}
						}
						if(!_status.selectionfull){
							ctx.lineTo(e.clientX/game.documentZoom-ui.arena.offsetLeft,e.clientY/game.documentZoom-ui.arena.offsetTop);
						}
						ctx.stroke();
						if(!_status.multitarget){
							for(var i=0;i<_status.lastdragchange.length;i++){
								ctx.moveTo(_status.mousedragging.clientX/game.documentZoom-ui.arena.offsetLeft,_status.mousedragging.clientY/game.documentZoom-ui.arena.offsetTop);
								var exy=_status.lastdragchange[i]._lastdragchange;
								ctx.lineTo(exy[0],exy[1]);
								ctx.stroke();
							}
						}
					}

					while(item){
						if(item==_status.mousedragorigin){
							if(_status.mouseleft){
								_status.mousedragging=null;
								_status.mousedragorigin=null;
								_status.clicked=false;
								if(_status.event.type=='phase'&&!_status.event.skill&&ui.confirm){
									ui.confirm.classList.add('removing');
								}
								game.uncheck();
								game.check();
								_status.clicked=true;
							}
							return;
						}
						var itemtype=get.itemtype(item);
						if(itemtype=='card'||itemtype=='button'||itemtype=='player'){
							_status.mouseleft=true;
							if(ui.selected.cards.length){
								ui.selected.cards[0].updateTransform(true,100);
							}
							var ex=e.clientX/game.documentZoom-ui.arena.offsetLeft;
							var ey=e.clientY/game.documentZoom-ui.arena.offsetTop;
							var exx=ex,eyy=ey;
							if(game.chess){
								ex-=-ui.chessContainer.chessLeft+ui.chess.offsetLeft;
								ey-=-ui.chessContainer.chessTop+ui.chess.offsetTop;
							}
							if(itemtype!='player'||game.chess||(ex>item.offsetLeft&&ex<item.offsetLeft+item.offsetWidth&&
								ey>item.offsetTop&&ey<item.offsetTop+item.offsetHeight)){
								var targetfixed=false;
								if(itemtype=='player'){
									if(get.select(_status.event.selectTarget)[1]<=-1){
										targetfixed=true;
									}
								}
								if(!targetfixed&&item.classList.contains('selectable')&&_status.dragstatuschanged!=item){
									_status.mouseleft=true;
									_status.dragstatuschanged=item;
									_status.clicked=false;
									var notbefore=itemtype=='player'&&!item.classList.contains('selected');
									ui.click[itemtype].call(item);
									if(item.classList.contains('selected')){
										if(notbefore){
											_status.lastdragchange.push(item);
											item._lastdragchange=[exx,eyy];
										}
									}
									else{
										_status.lastdragchange.remove(item);
									}
									_status.selectionfull=true;
									if(_status.event.filterButton&&ui.selected.buttons.length<get.select(_status.event.selectButton)[1]){
										_status.selectionfull=false;
									}
									else if(_status.event.filterCard&&ui.selected.cards.length<get.select(_status.event.selectCard)[1]){
										_status.selectionfull=false;
									}
									else if(_status.event.filterTarget&&ui.selected.targets.length<get.select(_status.event.selectTarget)[1]){
										_status.selectionfull=false;
									}
								}
							}
							return;
						}
						item=item.parentNode;
					}
					if(!_status.mouseleft){
						_status.mouseleft=true;
						game.check();
						for(var i=0;i<ui.selected.cards.length;i++){
							ui.selected.cards[i].updateTransform(true);
						}
					}
					_status.dragstatuschanged=null;
				}
				else{
					while(item){
						if(item==node&&!node._mouseentercreated){
							ui.click.mouseentercancel();
							var hoveration;
							if(typeof node._hoveration=='number'){
								hoveration=node._hoveration;
							}
							else{
								hoveration=parseInt(lib.config.hoveration);
								if(node.classList.contains('button')||
									(node.parentNode&&node.parentNode.parentNode)==ui.me){
									hoveration+=500;
								}
							}
							_status._mouseentertimeout=setTimeout(function(){
								if(_status.currentmouseenter!=node||node._mouseentercreated||_status.tempunpopup||
									_status.mousedragging||_status.mousedown||!node.offsetWidth||!node.offsetHeight){
									return;
								}
								if(node._hoverfunc&&!node._nopup){
									var dialog=node._hoverfunc.call(node,e);
									if(dialog){
										dialog.classList.add('popped');
										ui.window.appendChild(dialog);
										lib.placePoppedDialog(dialog,e);
										if(node._hoverwidth){
											dialog.style.width=node._hoverwidth+'px';
											dialog._hovercustomed=true;
										}
										node._mouseenterdialog=dialog;
										node._mouseentercreated=true;
									}
								}
							},hoveration);
							break;
						}
						item=item.parentNode;
					}
					if(_status.draggingdialog){
						var ddialog=_status.draggingdialog;
						if(ddialog._dragorigin&&ddialog._dragtransform){
							var translate=ddialog._dragtransform.slice(0);
							translate[0]+=e.clientX/game.documentZoom-ddialog._dragorigin.clientX/game.documentZoom;
							translate[1]+=e.clientY/game.documentZoom-ddialog._dragorigin.clientY/game.documentZoom;
							ui.click.checkdialogtranslate(translate,ddialog);
						}
						_status.clicked=true;
					}
					if(_status.draggingroundmenu){
						if(ui.roundmenu._dragorigin&&ui.roundmenu._dragtransform){
							var translate=ui.roundmenu._dragtransform.slice(0);
							translate[0]+=e.clientX/game.documentZoom-ui.roundmenu._dragorigin.clientX/game.documentZoom;
							translate[1]+=e.clientY/game.documentZoom-ui.roundmenu._dragorigin.clientY/game.documentZoom;
							ui.click.checkroundtranslate(translate);
						}
						_status.clicked=true;
					}
				}
			},
			windowmousedown:function(e){
				if(window.inSplash) return;
				if(!ui.window) return;
				if(e.button==2) return;
				_status.mousedown=true;
				var dialogs=ui.window.querySelectorAll('#window>.dialog.popped:not(.static)');
				for(var i=0;i<dialogs.length;i++){
					dialogs[i].delete();
				}
				var sourceitem=document.elementFromPoint(e.clientX,e.clientY);
				var item=sourceitem;
				while(item){
					var itemtype=get.itemtype(item);
					if(itemtype=='button') break;
					if(itemtype=='dialog'&&
					!item.classList.contains('popped')&&
					!item.classList.contains('fixed')){
						var ddialog=item;
						_status.draggingdialog=ddialog;
						ddialog._dragorigin=e;
						if(!ddialog._dragtransform){
							ddialog._dragtransform=[0,0];
						}
						return;
					}
					if(item==ui.roundmenu){
						_status.draggingroundmenu=true;
						ui.roundmenu._dragorigin=e;
						if(!ui.roundmenu._dragtransform){
							ui.roundmenu._dragtransform=[0,0];
						}
						return;
					}
					item=item.parentNode;
				}

				var evt=_status.event;
				if(!lib.config.enable_drag) return;
				if(!ui.arena.classList.contains('selecting')) return;
				if(!evt.isMine()) return;

				item=sourceitem;
				while(item){
					var itemtype=get.itemtype(item);
					if(itemtype=='card'||itemtype=='button'||itemtype=='player'){
						if(item.classList.contains('selectable')&&
							!item.classList.contains('selected')&&
							!item.classList.contains('noclick')){
							_status.clicked=false;
							ui.click[itemtype].call(item);
							if(item.classList.contains('selected')){
								_status.mousedragging=e;
								_status.mousedragorigin=item;
								_status.mouseleft=false;
								_status.selectionfull=false;
								_status.multitarget=false;
								_status.lastmouseutc=get.utc();
								ui.arena.classList.add('dragging');
							}
						}
						return;
					}
					item=item.parentNode;
				}
			},
			cardtouchstart:function(e){
				if(e.touches.length!=1) return;
				if(!lib.config.enable_drag) return;
				if(!this.parentNode) return;
				if(!this.parentNode.parentNode) return;
				if(this.parentNode.parentNode.parentNode!=ui.me) return;
				if(this.parentNode.parentNode.classList.contains('scrollh')) return;
				if(this.classList.contains('selectable')&&
					!this.classList.contains('selected')&&
					!this.classList.contains('noclick')){
					this._waitingfordrag={
						clientX:e.touches[0].clientX,
						clientY:e.touches[0].clientY
					};
				}
			},
			cardtouchmove:function(e){
				ui.click.longpresscancel.call(this);
				if(this._waitingfordrag){
					var drag=this._waitingfordrag;
					_status.clicked=false;
					_status.touchnocheck=true;
					ui.click.card.call(this);
					_status.touchnocheck=false;
					if(this.classList.contains('selected')){
						_status.mousedragging=drag;
						_status.mousedragorigin=this;
						_status.mouseleft=false;
						_status.selectionfull=false;
						_status.multitarget=false;
					}
					delete this._waitingfordrag;
				}
			},
			windowmouseup:function(e){
				delete _status.force;
				// if(_status.forcetouchinterval){
				// 	clearInterval(_status.forcetouchinterval);
				// 	delete _status.forcetouchinterval;
				// }
				if(window.inSplash) return;
				if(_status.draggingdialog){
					var ddialog=_status.draggingdialog;
					var translate;
					if(ddialog._dragorigin&&ddialog._dragtransform){
						translate=ddialog._dragtransform;
						translate[0]+=e.clientX/game.documentZoom-ddialog._dragorigin.clientX/game.documentZoom;
						translate[1]+=e.clientY/game.documentZoom-ddialog._dragorigin.clientY/game.documentZoom;
						ui.click.checkdialogtranslate(null,ddialog);
						delete ddialog._dragorigin;
					}
					game.saveConfig('dialog_transform',translate);
					delete _status.draggingdialog;
				}
				if(_status.draggingroundmenu){
					var translate;
					if(ui.roundmenu._dragorigin&&ui.roundmenu._dragtransform){
						var dx=e.clientX/game.documentZoom-ui.roundmenu._dragorigin.clientX/game.documentZoom;
						var dy=e.clientY/game.documentZoom-ui.roundmenu._dragorigin.clientY/game.documentZoom;
						if(dx*dx+dy*dy<25){
							ui.click.roundmenu();
						}
						translate=ui.roundmenu._dragtransform;
						translate[0]+=dx;
						translate[1]+=dy;
						ui.click.checkroundtranslate();
						delete ui.roundmenu._dragorigin;
					}
					game.saveConfig('roundmenu_transform',translate);
					delete _status.draggingroundmenu;
				}
				if(e.button==2){
					if(_status.mousedragging){
						_status.mousedragging=null;
						_status.mouseleft=false;
						_status.mousedragorigin=null;
						_status.dragstatuschanged=false;
						game.uncheck();
						game.check();
						_status.noright=true;
					}
				}
				else{
					var tmpflag=false;
					_status.mousedown=false;
					for(var i=0;i<ui.selected.cards.length;i++){
						ui.selected.cards[i].updateTransform(true);
					}
					if(_status.mousedragging&&_status.mouseleft){
						if(game.check()){
							if(ui.confirm){
								ui.confirm.close();
							}
							var event=_status.event;
							if(!event.filterOk||event.filterOk()) ui.click.ok();
						}
						else{
							game.uncheck();
							game.check();
						}
					}
					else if(_status.mousedragging&&_status.mousedragorigin){
						tmpflag=_status.mousedragorigin;
					}
					_status.lastdragchange.length=0;
					_status.mousedragging=null;
					_status.mouseleft=false;
					_status.mousedragorigin=null;
					_status.dragstatuschanged=false;
					if(ui.arena){
						ui.canvas.width=ui.arena.offsetWidth;
						ui.canvas.height=ui.arena.offsetHeight;
					}
					if(tmpflag){
						ui.click[get.itemtype(tmpflag)].call(tmpflag);
						game.check();
					}
					// ui.updatehl();
				}
				if(ui.arena){
					ui.arena.classList.remove('dragging');
				}
			},
			mousemove:function(){
				if(!lib.config.hover_handcard&&this.parentNode&&this.parentNode.parentNode==ui.me){
					return;
				}
				if(!_status.currentmouseenter){
					_status.currentmouseenter=this;
				}
			},
			mouseenter:function(){
				if(!lib.config.hover_handcard&&this.parentNode&&this.parentNode.parentNode==ui.me){
					return;
				}
				_status.currentmouseenter=this;
			},
			mouseleave:function(){
				ui.click.mouseentercancel();
				if(_status.currentmouseenter==this){
					_status.currentmouseenter=null;
				}
				this._mouseentercreated=false;
			},
			mousedown:function(){
				ui.click.mouseentercancel();
				if(_status.currentmouseenter==this){
					_status.currentmouseenter=null;
				}
				this._mouseentercreated=true;
			},
			mouseentercancel:function(){
				if(_status._mouseentertimeout){
					clearTimeout(_status._mouseentertimeout);
					delete _status._mouseentertimeout
				}
			},
			hoverplayer:function(e){
				var node=get.nodeintro(this,true);
				if(node) node.style.zIndex=21;
				return node;
			},
			longpressdown:function(e){
				if(_status.longpressed) return;
				if(this._longpresstimeout){
					clearTimeout(this._longpresstimeout);
				}
				if(lib.config.longpress_info){
					this._longpresstimeout=setTimeout(ui.click.longpresscallback,500);
				}
				this._longpressevent=e;
				if(_status.longpressing&&_status.longpressing!=this){
					ui.click.longpresscancel.call(_status.longpressing);
				}
				// if(window.ForceTouch&&!_status.forcetouchinterval&&lib.config.enable_pressure){
				// 	_status.forcetouchinterval=setInterval(ui.click.forcetouch,30);
				// }
				_status.longpressing=this;
			},
			longpresscallback:function(){
				if(!_status.longpressing) return;
				var node=_status.longpressing;
				var func=node._longpresscallback;
				var e=node._longpressevent;
				if(!func||!e) return;
				clearTimeout(node._longpresstimeout);
				_status.force=true;
				delete _status.longpressing;
				delete node._longpresstimeout;
				delete node._longpressevent;
				if(_status.mousedragging&&_status.mouseleft) return;
				if(!_status.longpressed){
					_status.longpressed=true;
					setTimeout(function(){
						_status.longpressed=false;
					},500);
					func.call(node,e);
					if(lib.config.touchscreen&&lib.config.enable_drag&&!node._waitingfordrag){
						_status.mousedragging=null;
						_status.mousedragorigin=null;
						_status.clicked=false;
						game.uncheck();
						game.check();
						_status.clicked=true;
					}
					delete node._waitingfordrag;
					ui.click.touchpop();
				}
			},
			longpresscancel:function(){
				if(this._longpresstimeout){
					clearTimeout(this._longpresstimeout);
					delete this._longpresstimeout;
				}
				delete this._longpressevent;
				if(_status.longpressing==this){
					delete _status.longpressing;
				}
			},
			window:function(){
				var clicked=_status.clicked;
				var dialogtouched=false;
				if(_status.dialogtouched){
					_status.dialogtouched=false;
					dialogtouched=true;
				}
				if(_status.dragged) return;
				if(_status.touchpopping) return;
				if(_status.reloading) return;
				if(_status.clicked||_status.clicked2){
					_status.clicked=false;
					_status.clicked2=false;
				}
				else{
					if(_status.clickingidentity){
						for(var i=0;i<_status.clickingidentity[1].length;i++){
							_status.clickingidentity[1][i].delete();
							_status.clickingidentity[1][i].style.transform='';
						}
						delete _status.clickingidentity;
					}
					if(!_status.event.isMine) return;
					if(ui.controls.length){
						ui.updatec();
					}
					if(_status.editing){
						if(_status.editing.innerHTML.length){
							_status.editing.link=_status.editing.innerHTML;
						}
						_status.editing.innerHTML=get.translation(_status.editing.link);
						delete _status.editing;
					}
					else if(_status.choosing){
						if(!_status.choosing.expand){
							_status.choosing.parentNode.style.height='';
							_status.choosing.nextSibling.delete();
							_status.choosing.previousSibling.show();
							delete _status.choosing;
						}
					}
					else if(ui.intro){
						ui.intro.close();
						delete ui.intro;
						ui.control.show();
						game.resume2();
					}
					else if((_status.event.isMine()||_status.event.forceMine)&&!dialogtouched){
						if(_status.event.custom&&_status.event.custom.replace.window){
							_status.event.custom.replace.window();
						}
						else{
							if(_status.event.skill&&_status.event.name=='chooseToUse'){
								ui.click.cancel();
							}
							else if(_status.event._checked){
								game.uncheck();
								game.check();
							}
						}
					}
					if(!ui.shortcut.classList.contains('hidden')){
						ui.click.shortcut(false);
					}
					if(get.is.phoneLayout()&&ui.menuContainer&&ui.menuContainer.classList.contains('hidden')){
						if(ui.system2.classList.contains('shown')){
							_status.removinground=true;
							setTimeout(function(){
								_status.removinground=false;
							},200);
						}
						ui.arena.classList.remove('phonetop');
						ui.system1.classList.remove('shown');
						ui.system2.classList.remove('shown');
						// if(ui.chessinfo){
						// 	ui.chessinfo.classList.remove('zoomed');
						// }
					}
				}
				if(_status.tempunpop){
					_status.tempunpop=false;
				}
				else{
					game.closePopped();
				}
				if(_status.event.custom&&_status.event.custom.add.window){
					_status.event.custom.add.window(clicked);
				}
			},
			toggle:function(){
				if(_status.dragged) return;
				if(this.parentNode.classList.contains('disabled')) return;
				_status.tempunpop=true;
				if(this.link){
					this.link=false;
					this.classList.remove('on');
					if(this.additionalCommand) this.additionalCommand(false,this.parentNode);
				}
				else{
					this.link=true;
					this.classList.add('on');
					if(this.additionalCommand) this.additionalCommand(true,this.parentNode);
				}
			},
			editor:function(){
				if(_status.dragged) return;
				if(_status.editing) return;
				_status.clicked=true;
				this.innerHTML='';
				_status.editing=this;
				if(this.additionalCommand) this.additionalCommand(this);
			},
			switcher:function(){
				if(_status.dragged) return;
				if(this.parentNode.classList.contains('disabled')) return;
				if(_status.choosing) return;
				_status.clicked=true;
				_status.tempunpop=true;
				this.previousSibling.hide();
				var node=ui.create.div('.switcher',this.parentNode).animate('start');
				for(var i=0;i<this.choice.length;i++){
					var choice=ui.create.div('.pointerdiv',node);
					choice.innerHTML=get.translation(this.choice[i]);
					choice.link=this.choice[i];
					choice.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.choice);
				}
				// this.parentNode.style.height=(node.offsetHeight)+'px';
				_status.choosing=this;
				if(!_status.choosing.expand){
					_status.choosing.expand=true;
					setTimeout(function(){
						_status.choosing.expand=false;
					},500);
				}
			},
			choice:function(){
				if(_status.dragged) return;
				if(!_status.choosing) return;
				_status.choosing.link=this.link;
				_status.choosing.innerHTML=get.translation(this.link);
				this.parentNode.parentNode.style.height='';
				this.parentNode.delete();
				_status.choosing.previousSibling.show();
				delete _status.choosing;
				if(this.parentNode.parentNode.querySelector('.toggle').additionalCommand){
					this.parentNode.parentNode.querySelector('.toggle').additionalCommand(this.link,this.parentNode.parentNode);
				}
			},
			button:function(){
				if(_status.dragged) return;
				if(_status.clicked) return;
				if(_status.tempNoButton) return;
				if(_status.draggingtouchdialog) return;
				if(this.classList.contains('noclick')) return;
				if(_status.justdragged) return;
				_status.clicked=true;
				var custom=_status.event.custom;
				if(custom&&custom.replace.button){
					custom.replace.button(this);
					return;
				}
				if(!_status.event.isMine()) return;
				if(this.classList.contains('selectable')==false) return;
				if(this.classList.contains('selected')){
					ui.selected.buttons.remove(this);
					this.classList.remove('selected');
					if(_status.multitarget||_status.event.complexSelect){
						game.uncheck();
						game.check();
					}
				}
				else{
					this.classList.add('selected');
					ui.selected.buttons.add(this);
				}
				if(custom&&custom.add&&custom.add.button){
					custom.add.button();
				}
				game.check();
			},
			touchintro:function(){
				var rect=this.getBoundingClientRect();
				ui.click.touchpop();
				ui.click.intro.call(this,{
					clientX:rect.left+18,
					clientY:rect.top+12
				});
				_status.clicked=false;
			},
			card:function(){
				delete this._waitingfordrag;
				if(_status.dragged) return;
				if(_status.clicked) return;
				if(ui.intro) return;
				_status.clicked=true;
				if(this.parentNode&&(this.parentNode.classList.contains('judges')||this.parentNode.classList.contains('marks'))){
					var rect=this.getBoundingClientRect();
					ui.click.touchpop();
					ui.click.intro.call(this,{
						clientX:rect.left+18,
						clientY:rect.top+12
					});
					_status.clicked=false;
					return;
				}
				var custom=_status.event.custom;
				if(custom&&custom.replace.card){
					custom.replace.card(this);
					return;
				}
				if(this.classList.contains('selectable')==false) return;
				if(this.classList.contains('selected')){
					ui.selected.cards.remove(this);
					if(_status.multitarget||_status.event.complexSelect){
						game.uncheck();
						game.check();
					}
					else{
						this.classList.remove('selected');
						this.updateTransform();
					}
				}
				else{
					ui.selected.cards.add(this);
					this.classList.add('selected');
					this.updateTransform(true);
				}
				if(game.chess&&get.config('show_range')&&!_status.event.skill&&this.classList.contains('selected')&&
				_status.event.isMine()&&_status.event.name=='chooseToUse'){
					var player=_status.event.player;
					var range=get.info(this).range;
					if(range){
						if(typeof range.attack==='number'){
							player.createRangeShadow(Math.min(8,player.getAttackRange(true)+range.attack-1));
						}
						else if(typeof range.global==='number'){
							player.createRangeShadow(Math.min(8,player.getGlobalFrom()+range.global));
						}
					}
				}
				if(custom.add.card){
					custom.add.card();
				}
				game.check();

				if(lib.config.popequip&&get.is.phoneLayout()&&
					arguments[0]!='popequip'&&ui.arena&&ui.arena.classList.contains('selecting')&&
					this.parentNode&&this.parentNode.classList.contains('popequip')){
					var rect=this.getBoundingClientRect();
					ui.click.touchpop();
					ui.click.intro.call(this.parentNode,{
						clientX:rect.left+18,
						clientY:rect.top+12
					});
				}
			},
			avatar:function(){
				if(!lib.config.doubleclick_intro) return;
				if(this.parentNode.isUnseen(0)) return;
				if(!lib.character[this.parentNode.name]) return;
				if(!ui.menuContainer) return;
				var avatar=this;
				var player=this.parentNode;
				if(!game.players.contains(player)&&!game.dead.contains(player)) return;
				if(!this._doubleClicking){
					this._doubleClicking=true;
					setTimeout(function(){
						avatar._doubleClicking=false;
					},500);
					return;
				}
				// ui.click.skin(this,player.name);
				game.pause2();
				ui.click.charactercard(player.name1||player.name,null,null,true,this);
			},
			avatar2:function(){
				if(!lib.config.doubleclick_intro) return;
				if(this.parentNode.classList.contains('unseen2')) return;
				if(!lib.character[this.parentNode.name2]) return;
				if(!ui.menuContainer) return;
				var avatar=this;
				var player=this.parentNode;
				if(!game.players.contains(player)&&!game.dead.contains(player)) return;
				if(!this._doubleClicking){
					this._doubleClicking=true;
					setTimeout(function(){
						avatar._doubleClicking=false;
					},500);
					return;
				}
				// ui.click.skin(this,player.name2);
				game.pause2();
				ui.click.charactercard(player.name2,null,null,true,this);
			},
			connectroom:function(e){
				if(_status.dragged) return;
				if(_status.clicked) return;
				if(ui.intro) return;
				if(this.roomfull){
					alert('房间已满');
				}
				else if(this.roomgaming&&!game.onlineID){
					if(this.config&&this.config.observe){
						alert('房间暂时不可旁观');
					}
					else{
						alert('房间不允许旁观');
					}
				}
				else if(!this.roomempty&&this.version!=lib.versionOL){
					if(this.version>lib.versionOL){
						alert('加入失败:你的游戏版本过低');
					}
					else{
						alert('加入失败:房主的游戏版本过低');
					}
				}
				else{
					if(!_status.enteringroom){
						_status.enteringroom=true;
						_status.enteringroomserver=this.serving;
						game.send('server','enter',this.key,get.connectNickname(),lib.config.connect_avatar);
					}
				}
			},
			player:function(){
				return ui.click.target.apply(this,arguments);
			},
			target:function(e){
				if(_status.dragged) return;
				if(_status.clicked) return;
				if(ui.intro) return;
				if(this.classList.contains('connect')){
					if(game.online){
						if(game.onlinezhu){
							if(!this.playerid&&game.connectPlayers){
								if(lib.configOL.mode=='versus'||lib.configOL.mode=='doudizhu') return;
								if(lib.configOL.mode=='identity'&&lib.configOL.identity_mode=='zhong') return;
								if(!this.classList.contains('unselectable2')&&lib.configOL.number<=2) return;
								this.classList.toggle('unselectable2')
								if(this.classList.contains('unselectable2')){
									lib.configOL.number--;
								}
								else{
									lib.configOL.number++;
								}
								game.send('changeNumConfig',lib.configOL.number,
								game.connectPlayers.indexOf(this),this.classList.contains('unselectable2'));
							}
						}
						return;
					}
					if(this.playerid){
						if(this.ws){
							if(confirm('是否踢出'+this.nickname+'?')){
								var id=get.id();
								this.ws.send(function(id){
									if(game.ws){
										game.ws.close();
										game.saveConfig('reconnect_info');
										game.saveConfig('banned_info',id);
									}
								},id);
								lib.node.banned.push(id);
							}
						}
					}
					else{
						if(lib.configOL.mode=='versus'||lib.configOL.mode=='doudizhu'||lib.configOL.mode=='single') return;
						if(lib.configOL.mode=='identity'&&(lib.configOL.identity_mode=='zhong'||lib.configOL.identity_mode=='purple')) return;
						if(!this.classList.contains('unselectable2')&&lib.configOL.number<=2) return;
						this.classList.toggle('unselectable2')
						if(this.classList.contains('unselectable2')){
							lib.configOL.number--;
						}
						else{
							lib.configOL.number++;
						}
						game.send('server','config',lib.configOL);
						game.updateWaiting();
					}
					return;
				}
				_status.clicked=true;
				var custom=_status.event.custom;
				if(custom&&custom.replace.target){
					custom.replace.target(this,e);
					return;
				}
				if(this.classList.contains('selectable')==false) return;
				this.unprompt();
				if(this.classList.contains('selected')){
					ui.selected.targets.remove(this);
					if(_status.multitarget||_status.event.complexSelect){
						game.uncheck();
						game.check();
					}
					else{
						this.classList.remove('selected');
					}
				}
				else{
					ui.selected.targets.add(this);
					if(_status.event.name=='chooseTarget'||_status.event.name=='chooseToUse'||_status.event.name=='chooseCardTarget'){
						var targetprompt=null;
						if(_status.event.targetprompt){
							targetprompt=_status.event.targetprompt;
						}
						else if(_status.event.skill&&!get.info(_status.event.skill).viewAs){
							targetprompt=get.info(_status.event.skill).targetprompt;
						}
						else if(_status.event.name=='chooseToUse'){
							var currentcard=get.card();
							if(currentcard){
								targetprompt=get.info(currentcard).targetprompt;
							}
						}
						if(targetprompt){
							if(Array.isArray(targetprompt)){
								targetprompt=targetprompt[Math.min(targetprompt.length-1,ui.selected.targets.indexOf(this))];
							}
							else if(typeof targetprompt=='function'){
								targetprompt=targetprompt(this);
							}
							if(targetprompt&&typeof targetprompt=='string'){
								this.prompt(targetprompt);
							}
						}
					}
					this.classList.add('selected');
				}
				if(custom.add.target){
					custom.add.target();
				}
				game.check();
			},
			control2:function(){
				if(this.childNodes.length==1&&!this._doubleclick){
					ui.click.control.call(this.firstChild);
				}
			},
			control:function(){
				if(_status.dragged) return;
				if(ui.control.classList.contains('hidden')) return;
				var node=this.parentNode;
				if(node){
					if(node._doubleclick){
						return;
					}
					else{
						node._doubleclick=true;
						setTimeout(function(){
							node._doubleclick=false;
						},500);
					}
					if(node.classList.contains('hidden')) return;
					if(node.classList.contains('removing')) return;
					if(node.classList.contains('disabled')) return;
				}
				if(ui.intro){
					ui.intro.close();
					delete ui.intro;
				}
				_status.clicked=true;
				if(this.parentNode.custom){
					this.parentNode.custom(this.link,this);
					return;
				}
				if(this.link=='ok'){
					ui.click.ok(this);
				}
				else if(this.link=='cancel'){
					ui.click.cancel(this);
				}
				else{
					_status.event.result={
						buttons:ui.selected.buttons.slice(0),
						cards:ui.selected.cards.slice(0),
						targets:ui.selected.targets.slice(0),
						control:this.link,
						links:get.links(ui.selected.buttons)
					};
					if(this.parentNode.close!=false){
						game.uncheck();
						this.parentNode.close();
					}
					game.resume();
				}
			},
			dialogcontrol:function(){
				_status.event.result={
					buttons:ui.selected.buttons.slice(0),
					cards:ui.selected.cards.slice(0),
					targets:ui.selected.targets.slice(0),
					control:this.link,
					links:get.links(ui.selected.buttons)
				};
				game.resume();
			},
			skill:function(skill){
				var info=get.info(skill);
				var event=_status.event;
				event.backup(skill);
				if(info.filterCard&&info.discard!=false&&info.lose!=false&&!info.viewAs){
					var cards=event.player.getCards(event.position);
					for(var i=0;i<cards.length;i++){
						if(!lib.filter.cardDiscardable(cards[i],event.player)){
							cards[i].uncheck('useSkill');
						}
					}
				}
				if(typeof event.skillDialog=='object'){
					event.skillDialog.close();
				}
				if(event.isMine()){
					event.skillDialog=true;
				}
				game.uncheck();
				game.check();
				if(event.skillDialog===true){
					var str=get.translation(skill);
					if(info.prompt){
						var str2;
						if(typeof info.prompt=='function'){
							str2=info.prompt(event);
						}
						else{
							str2=info.prompt;
						}
						event.skillDialog=ui.create.dialog(str,'<div><div style="width:100%;text-align:center">'+str2+'</div></div>');
						if(info.longprompt){
							event.skillDialog.forcebutton=true;
							ui.update();
						}
					}
					else if(info.promptfunc){
						event.skillDialog=ui.create.dialog(str,'<div><div style="width:100%">'+info.promptfunc(event,event.player)+'</div></div>');
					}
					else if(lib.dynamicTranslate[skill]){
						event.skillDialog=ui.create.dialog(str,'<div><div style="width:100%">'+lib.dynamicTranslate[skill](event.player,skill)+'</div></div>');
					}
					else if(lib.translate[skill+'_info']){
						event.skillDialog=ui.create.dialog(str,'<div><div style="width:100%">'+lib.translate[skill+'_info']+'</div></div>');
					}
				}
			},
			ok:function(node){
				var event=_status.event;
				if(event.custom&&event.custom.replace.confirm){
					event.custom.replace.confirm(true);return;
				}
				event.result={
					buttons:ui.selected.buttons.slice(0),
					cards:ui.selected.cards.slice(0),
					targets:ui.selected.targets.slice(0),
					confirm:'ok',
					bool:true,
					links:get.links(ui.selected.buttons)
				};
				if(node){
					node.parentNode.close();
				}
				if(event.skill){
					event.result.skill=event.skill;
					if(typeof get.info(event.skill).viewAs=='function') event.result.card=get.info(event.skill).viewAs(event.result.cards,event.player);
					else event.result.card=get.copy(get.info(event.skill).viewAs);
					if(event.result.cards.length==1&&event.result.card){
						if(!event.result.card.suit) event.result.card.suit=get.suit(event.result.cards[0]);
						if(!event.result.card.number) event.result.card.number=get.number(event.result.cards[0]);
					}
					if(event.skillDialog&&get.objtype(event.skillDialog)=='div'){
						event.skillDialog.close();
					}
					var cards=event.player.getCards('hej');
					for(var i=0;i<cards.length;i++){
						cards[i].recheck('useSkill');
					}
					event.restore();
				}
				else if(event.name=='chooseToUse'||event.name=='chooseToRespond'){
					event.result.card=get.autoViewAs(event.result.cards[0]);
				}
				if(ui.skills) ui.skills.close();
				if(ui.skills2) ui.skills2.close();
				if(ui.skills3) ui.skills3.close();
				game.uncheck();
				if(event.custom.add.confirm){
					event.custom.add.confirm(true);
				}
				game.resume();
			},
			cancel:function(node){
				var event=_status.event;
				if(event.custom.replace.confirm){
					event.custom.replace.confirm(false);return;
				}
				if(event.skill&&!event.norestore){
					if(event.skillDialog&&get.objtype(event.skillDialog)=='div'){
						event.skillDialog.close();
					}
					if(typeof event.dialog=='string'&&event.isMine()){
						event.dialog=ui.create.dialog(event.dialog);
					}
					if(_status.event.type=='phase'&&ui.confirm){
						ui.confirm.classList.add('removing');
					}
					// ui.control.animate('nozoom',100);
					event.restore();
					var cards=event.player.getCards('hej');
					for(var i=0;i<cards.length;i++){
						cards[i].recheck('useSkill');
					}
					game.uncheck();
					game.check();
					return;
				}
				event.result={
					confirm:'cancel',
					bool:false
				};
				if(node){
					node.parentNode.close();
				}
				if(ui.skills) ui.skills.close();
				if(ui.skills2) ui.skills2.close();
				if(ui.skills3) ui.skills3.close();
				game.uncheck();
				if(event.custom.add.confirm){
					event.custom.add.confirm(true);
				}
				game.resume();
			},
			logv:function(e){
				if(_status.currentlogv){
					if(_status.currentlogv==this) return;
					if(_status.logvtimeout){
						clearTimeout(_status.logvtimeout);
					}
					var that=this;
					_status.logvtimeout=setTimeout(function(){
						if(!_status.currentlogv){
							_status.currentlogv=that;
							ui.click.intro.call(that,e);
						}
					},200);
					this.logvtimeout=_status.logvtimeout;
				}
				else{
					_status.currentlogv=this;
					ui.click.intro.call(this,e);
				}
			},
			logvleave:function(){
				if(_status.currentlogv==this){
					setTimeout(function(){
						delete _status.currentlogv;
					},150);
				}
				if(this.logvtimeout){
					clearTimeout(this.logvtimeout);
					if(_status.logvtimeout==this.logvtimeout){
						delete _status.logvtimeout;
					}
					delete this.logvtimeout;
				}
			},
			charactercard:function(name,sourcenode,noedit,resume,avatar){
				if(_status.dragged) return;
				if(lib.config.theme!='simple'){
					ui.window.classList.add('shortcutpaused');
					ui.menuContainer.classList.add('forceopaque');
				}
				else{
					ui.window.classList.add('systempaused');
					ui.menuContainer.classList.add('transparent2');
				}
				if(lib.config.blur_ui){
					ui.arena.classList.add('blur');
					ui.system.classList.add('blur');
					ui.menuContainer.classList.add('blur');
				}
				var layer=ui.create.div('.popup-container');
				var clicklayer=function(e){
					if(_status.touchpopping) return;
					if(_status.dragged) return;
					ui.window.classList.remove('shortcutpaused');
					ui.window.classList.remove('systempaused');
					ui.menuContainer.classList.remove('forceopaque');
					ui.menuContainer.classList.remove('transparent2');
					ui.arena.classList.remove('blur');
					ui.system.classList.remove('blur');
					ui.menuContainer.classList.remove('blur');
					this.delete();
					e.stopPropagation();
					if(resume) game.resume2();
					return false;
				}
				var uiintro=ui.create.div('.menubg.charactercard',layer);
				var playerbg=ui.create.div('.menubutton.large.ava',uiintro);
				var bg=ui.create.div('.avatar',playerbg,function(){
					if(changeskinfunc){
						changeskinfunc();
					}
				}).setBackground(name,'character');
				var changeskinfunc=null;
				var nameskin=name;
				var nameskin2=name;
				var gzbool=false;
				if(nameskin.startsWith('gz_shibing')){
					nameskin=nameskin.slice(3,11);
				}
				else if(nameskin.startsWith('gz_')){
					nameskin=nameskin.slice(3);
					gzbool=true;
				}
				var changeskin=function(){
					var node=ui.create.div('.changeskin','可换肤',playerbg);
					var avatars=ui.create.div('.avatars',playerbg);
					changeskinfunc=function(){
						playerbg.classList.add('scroll');
						if(node._created){
							return;
						}
						node._created=true;
						var createButtons=function(num){
							if(!num) return;
							if(num>=4){
								avatars.classList.add('scroll');
								if(lib.config.touchscreen){
									lib.setScroll(avatars);
								}
							}
							for(var i=0;i<=num;i++){
								var button=ui.create.div(avatars,function(){
									playerbg.classList.remove('scroll');
									if(this._link){
										lib.config.skin[nameskin]=this._link;
										bg.style.backgroundImage=this.style.backgroundImage;
										if(sourcenode) sourcenode.style.backgroundImage=this.style.backgroundImage;
										if(avatar) avatar.style.backgroundImage=this.style.backgroundImage;
										game.saveConfig('skin',lib.config.skin);
									}
									else{
										delete lib.config.skin[nameskin];
										if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin){
											bg.setBackground(nameskin2,'character');
											if(sourcenode) sourcenode.setBackground(nameskin2,'character');
											if(avatar) avatar.setBackground(nameskin2,'character');
										}
										else{
											bg.setBackground(nameskin,'character');
											if(sourcenode) sourcenode.setBackground(nameskin,'character');
											if(avatar) avatar.setBackground(nameskin,'character');
										}
										game.saveConfig('skin',lib.config.skin);
									}
								});
								button._link=i;
								if(i){
									button.setBackgroundImage('image/skin/'+nameskin+'/'+i+'.jpg');
								}
								else{
									if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) button.setBackground(nameskin2,'character','noskin');
									else button.setBackground(nameskin,'character','noskin');
								}
							}
						};
						var num=1;
						var loadImage=function(){
							var img=new Image();
							img.onload=function(){
								num++;
								loadImage();
							}
							img.onerror=function(){
								num--;
								createButtons(num);
							}
							img.src=lib.assetURL+'image/skin/'+nameskin+'/'+num+'.jpg';
						}
						if(lib.config.change_skin){
							loadImage();
						}
						else{
							createButtons(lib.skin[nameskin]);
						}
					};
				};
				if(lib.config.change_skin){
					var img=new Image();
					img.onload=changeskin;
					img.src=lib.assetURL+'image/skin/'+nameskin+'/1.jpg';
				}
				else if(lib.config.debug&&lib.skin[nameskin]){
					changeskin();
				}
				var ban=ui.create.div('.menubutton.large.ban.character',uiintro,'禁用',function(e){
					if(this.classList.contains('unselectable')) return;
					if(typeof noedit=='string'){
						this.classList.toggle('active');
						var bannedname=noedit+'_banned';
						if(!lib.config[bannedname]){
							lib.config[bannedname]=[];
						}
						if(this.classList.contains('active')){
							lib.config[bannedname].add(name);
						}
						else{
							lib.config[bannedname].remove(name);
						}
						game.saveConfig(bannedname,lib.config[bannedname]);
						ban.updateBanned();
					}
					else{
						ui.click.touchpop();
						ui.click.intro.call(this,e);
						_status.clicked=true;
					}
				});
				ban.link=name;
				ban._banning='offline';
				ban.updateBanned=function(){
					if(noedit===true) return;
					if(lib.config[get.mode()+'_banned']&&lib.config[get.mode()+'_banned'].contains(name)){
						ban.classList.add('active');
					}
					else{
						ban.classList.remove('active');
					}
					if(sourcenode&&sourcenode.updateBanned){
						sourcenode.updateBanned();
					}
				};
				ban.updateBanned();
				var fav=ui.create.div('.menubutton.large.fav',uiintro,'收藏',function(){
					if(this.classList.contains('unselectable')) return;
					this.classList.toggle('active');
					if(this.classList.contains('active')){
						lib.config.favouriteCharacter.add(name);
					}
					else{
						lib.config.favouriteCharacter.remove(name);
					}
					game.saveConfig('favouriteCharacter',lib.config.favouriteCharacter);
				});
				if(noedit===true){
					fav.classList.add('unselectable');
					ban.classList.add('unselectable');
				}
				else if(lib.config.favouriteCharacter.contains(name)){
					fav.classList.add('active');
				}
				
				// 样式二
				if(lib.config.show_characternamepinyin=='showPinyin2'||lib.config.show_skillnamepinyin=='showPinyin2'||lib.config.show_characternamepinyin=='showCodeIdentifier2'||lib.config.show_skillnamepinyin=='showCodeIdentifier2'){
					var intro=ui.create.div('.characterintro',get.characterIntro(name),uiintro);
					if(lib.config.show_characternamepinyin=='showPinyin2'||lib.config.show_characternamepinyin=='showCodeIdentifier2'){
						var charactername=get.rawName2(name);
						var characterpinyin=lib.config.show_characternamepinyin=='showCodeIdentifier2'?name:get.pinyin(charactername);
						var nameinfo=get.character(name);
						var charactersex=get.translation(nameinfo[0]);
						const charactergroups=get.is.double(name,true);
						let charactergroup;
						if(charactergroups) charactergroup=charactergroups.map(i=>get.translation(i)).join('/')
						else charactergroup=get.translation(nameinfo[1]);
						var characterhp=nameinfo[2];
						var characterintroinfo=get.characterIntro(name);
						var spacemark=' | ';
						if(charactername.length>3) spacemark='<span style="font-size:7px">'+' '+'</span>'+'|'+'<span style="font-size:7px">'+' '+'</span>';
						intro.innerHTML='<span style="font-weight:bold;margin-right:5px">'+charactername+'</span>'+'<span style="font-size:14px;font-family:SimHei,STHeiti,sans-serif">'+'['+characterpinyin+']'+'</span>'+spacemark+charactersex+spacemark+charactergroup+spacemark+characterhp+'<span style="line-height:2"></span>'+'<br>'+characterintroinfo;
					}
					var intro2=ui.create.div('.characterintro.intro2',uiintro);
					var list=get.character(name,3)||[];
					var skills=ui.create.div('.characterskill',uiintro);
					if(lib.config.touchscreen){
						lib.setScroll(intro);
						lib.setScroll(intro2);
						lib.setScroll(skills);
					}

					if(lib.config.mousewheel){
						skills.onmousewheel=ui.click.mousewheel;
					}
					var clickSkill=function(e){
						while(intro2.firstChild){
							intro2.removeChild(intro2.lastChild);
						}
						var current=this.parentNode.querySelector('.active');
						if(current){
							current.classList.remove('active');
						}
						this.classList.add('active');
						var skillname=get.translation(this.link);
						var skilltranslationinfo=get.skillInfoTranslation(this.link);
						if((lib.config.show_skillnamepinyin=='showPinyin2'||lib.config.show_skillnamepinyin=='showCodeIdentifier2')&&skillname!='阵亡'){
							var skillpinyin=lib.config.show_skillnamepinyin=='showCodeIdentifier2'?this.link:get.pinyin(skillname);
							intro2.innerHTML='<span style="font-weight:bold;margin-right:5px">'+skillname+'</span>'+'<span style="font-size:14px;font-family:SimHei,STHeiti,sans-serif">'+'['+skillpinyin+']'+'</span>'+'  '+skilltranslationinfo;
						}else{
							intro2.innerHTML='<span style="font-weight:bold;margin-right:5px">'+skillname+'</span>'+skilltranslationinfo;
						}
						var info=get.info(this.link);
						var skill=this.link;
						var playername=this.linkname;
						var skillnode=this;
						if(info.derivation){
							var derivation=info.derivation;
							if(typeof derivation=='string'){
								derivation=[derivation];
							}
							for(var i=0;i<derivation.length;i++){
								var derivationname=get.translation(derivation[i]);
								var derivationtranslationinfo=get.skillInfoTranslation(derivation[i]);
								if((lib.config.show_skillnamepinyin=='showPinyin2'||lib.config.show_skillnamepinyin=='showCodeIdentifier2')&&derivationname.length<=5&&derivation[i].indexOf('_faq')==-1){
									var derivationpinyin=lib.config.show_skillnamepinyin=='showCodeIdentifier2'?derivation[i]:get.pinyin(derivationname);
									intro2.innerHTML+='<br><br><span style="font-weight:bold;margin-right:5px">'+derivationname+'</span>'+'<span style="font-size:14px;font-family:SimHei,STHeiti,sans-serif">'+'['+derivationpinyin+']'+'</span>'+'  '+derivationtranslationinfo;
								}else{
									intro2.innerHTML+='<br><br><span style="font-weight:bold;margin-right:5px">'+derivationname+'</span>'+derivationtranslationinfo;
								}
							}
						}
						if(info.alter){
							intro2.innerHTML+='<br><br><div class="hrefnode skillversion"></div>';
							var skillversionnode=intro2.querySelector('.hrefnode.skillversion');
							if(lib.config.vintageSkills.contains(skill)){
								skillversionnode.innerHTML='切换至新版';
							}
							else{
								skillversionnode.innerHTML='切换至旧版';
							}
							skillversionnode.listen(function(){
								if(lib.config.vintageSkills.contains(skill)){
									lib.config.vintageSkills.remove(skill);
									lib.translate[skill+'_info']=lib.translate[skill+'_info_alter'];
								}
								else{
									lib.config.vintageSkills.push(skill);
									lib.translate[skill+'_info']=lib.translate[skill+'_info_origin'];
								}
								game.saveConfig('vintageSkills',lib.config.vintageSkills);
								clickSkill.call(skillnode,'init');
							});
						}
						// if(e!=='init') game.trySkillAudio(this.link,playername);
						// 有bug,先用旧版
						if(lib.config.background_speak&&e!=='init'){
							var audioname=this.link;
							if(info.audioname2&&info.audioname2[playername]){
								audioname=info.audioname2[playername];
								info=lib.skill[audioname];
							}
							var audioinfo=info.audio;
							var that=this;
							var getIndex=function(i){
								if(typeof that.audioindex!='number'){
									that.audioindex=i;
								}
								that.audioindex++;
								if(that.audioindex>i){
									that.audioindex=1;
								}
								return that.audioindex;
							};
							if(typeof audioinfo=='string'){
								if(audioinfo.indexOf('ext:')==0){
									audioinfo=audioinfo.split(':');
									if(audioinfo.length==3){
										if(audioinfo[2]=='true'){
											game.playAudio('..','extension',audioinfo[1],audioname);
										}
										else{
											audioinfo[2]=parseInt(audioinfo[2]);
											if(audioinfo[2]){
												game.playAudio('..','extension',audioinfo[1],audioname+getIndex(audioinfo[2]));
											}
										}
									}
									return;
								}
								else{
									audioname=audioinfo;
									if(lib.skill[audioinfo]){
										audioinfo=lib.skill[audioinfo].audio;
									}
								}
							}
							else if(Array.isArray(audioinfo)){
								audioname=audioinfo[0];
								audioinfo=audioinfo[1];
							}
							if(typeof audioinfo=='number'){
								if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername;
								game.playAudio('skill',audioname+getIndex(audioinfo));
							}
							else if(typeof audioinfo=="object"&&"type" in audioinfo&&audioinfo.type=="direct"&&"files" in audioinfo){
								let audioFiles=audioinfo.files;
								if(typeof audioFiles=="object"){
									if(!Array.isArray(audioFiles)&&playername&&playername in audioFiles)audioFiles=audioFiles[playername];
									if(Array.isArray(audioFiles)){
										const length=audioFiles.length;
										game.playAudio(audioFiles[getIndex(length)-1]);
									}
								}
							}
							else if(audioinfo){
								if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername;
								game.playAudio('skill',audioname);
							}
							else if(true&&info.audio!==false){
								if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername;
								game.playSkillAudio(audioname,getIndex(2));
							}
						}
					}
				}else{
					// 样式一
					const introduction=ui.create.div('.characterintro',uiintro),showCharacterNamePinyin=lib.config.show_characternamepinyin;
					if(showCharacterNamePinyin!='doNotShow'){
						const characterIntroTable=ui.create.div('.character-intro-table',introduction),span=document.createElement('span');
						span.style.fontWeight='bold';
						const nameInfo=get.character(name),exInfo=nameInfo[4],characterName=exInfo&&exInfo.includes('ruby')?lib.translate[name]:get.rawName2(name);
						span.innerHTML=characterName;
						const ruby=document.createElement('ruby');
						ruby.appendChild(span);
						const leftParenthesisRP=document.createElement('rp');
						leftParenthesisRP.textContent='(';
						ruby.appendChild(leftParenthesisRP);
						const rt=document.createElement('rt');
						rt.innerHTML=showCharacterNamePinyin=='showCodeIdentifier'?name:lib.translate[`${name}_rt`]||get.pinyin(characterName).join(' ');
						ruby.appendChild(rt);
						const rightParenthesisRP=document.createElement('rp');
						rightParenthesisRP.textContent=')';
						ruby.appendChild(rightParenthesisRP);
						characterIntroTable.appendChild(ruby);
						const characterSexDiv=ui.create.div('.character-sex',characterIntroTable),exInfoSex=exInfo&&exInfo.find(value=>value.startsWith('sex:')),characterSex=exInfoSex?exInfoSex.split(':').pop():nameInfo[0];
						new Promise((resolve,reject)=>{
							const imageName=`sex_${characterSex}`,information=lib.card[imageName];
							if(!information) {
								resolve(`${lib.assetURL}image/card/${imageName}.png`)
								return;
							};
							const image=information.image;
							if(!image) resolve(`${lib.assetURL}image/card/${imageName}.png`);
							else if(image.startsWith('db:')) game.getDB('image',image.slice(3)).then(resolve,reject);
							else if(image.startsWith('ext:')) resolve(`${lib.assetURL}${image.replace(/^ext:/,'extension/')}`);
							else resolve(`${lib.assetURL}${image}`);
						}).then(source=>new Promise((resolve,reject)=>{
							const image=new Image();
							image.onload=()=>resolve(image);
							image.onerror=reject;
							image.src=source;
						})).then(image=>characterSexDiv.appendChild(image)).catch(()=>characterSexDiv.innerHTML=get.translation(characterSex));
						const characterGroupDiv=ui.create.div('.character-group',characterIntroTable),characterGroups=get.is.double(name,true);
						if(characterGroups) Promise.all(characterGroups.map(characterGroup=>new Promise((resolve,reject)=>{
							const imageName=`group_${characterGroup}`,information=lib.card[imageName];
							if(!information) resolve(`${lib.assetURL}image/card/${imageName}.png`);
							const image=information.image;
							if(!image) resolve(`${lib.assetURL}image/card/${imageName}.png`);
							else if(image.startsWith('db:')) game.getDB('image',image.slice(3)).then(resolve,reject);
							else if(image.startsWith('ext:')) resolve(`${lib.assetURL}${image.replace(/^ext:/,'extension/')}`);
							else resolve(`${lib.assetURL}${image}`);
						}).then(source=>new Promise((resolve,reject)=>{
							const image=new Image();
							image.onload=()=>resolve(image);
							image.onerror=reject;
							image.src=source;
						})))).then(images=>{
							let documentFragment=document.createDocumentFragment();
							images.forEach(documentFragment.appendChild,documentFragment);
							characterGroupDiv.appendChild(documentFragment);
						}).catch(()=>characterGroupDiv.innerHTML=characterGroups.map(characterGroup=>get.translation(characterGroup)).join('/'));
						else{
							const characterGroup=nameInfo[1];
							new Promise((resolve,reject)=>{
								const imageName=`group_${characterGroup}`,information=lib.card[imageName];
								if(!information) resolve(`${lib.assetURL}image/card/${imageName}.png`);
								const image=information.image;
								if(!image) resolve(`${lib.assetURL}image/card/${imageName}.png`);
								else if(image.startsWith('db:')) game.getDB('image',image.slice(3)).then(resolve,reject);
								else if(image.startsWith('ext:')) resolve(`${lib.assetURL}${image.replace(/^ext:/,'extension/')}`);
								else resolve(`${lib.assetURL}${image}`);
							}).then(source=>new Promise((resolve,reject)=>{
								const image=new Image();
								image.onload=()=>resolve(image);
								image.onerror=reject;
								image.src=source;
							})).then(image=>characterGroupDiv.appendChild(image)).catch(()=>characterGroupDiv.innerHTML=get.translation(characterGroup));
						}
						const hpDiv=ui.create.div('.hp',characterIntroTable),nameInfoHP=nameInfo[2],infoHP=get.infoHp(nameInfoHP);
						hpDiv.dataset.condition=infoHP<4?'mid':'high';
						ui.create.div(hpDiv);
						const hpTextDiv=ui.create.div('.text',hpDiv),infoMaxHP=get.infoMaxHp(nameInfoHP);
						hpTextDiv.innerHTML=infoHP==infoMaxHP?`×${infoHP}`:`×${infoHP}/${infoMaxHP}`;
						const infoShield=get.infoHujia(nameInfoHP);
						if(infoShield){
							ui.create.div('.shield',hpDiv);
							const shieldTextDiv=ui.create.div('.text',hpDiv);
							shieldTextDiv.innerHTML=`×${infoShield}`;
						}
						introduction.appendChild(document.createElement('hr'));
					}
					const htmlParser=document.createElement('body');
					htmlParser.innerHTML=get.characterIntro(name);
					Array.from(htmlParser.childNodes).forEach(value=>introduction.appendChild(value));
					const introduction2=ui.create.div('.characterintro.intro2',uiintro);
					var list=get.character(name,3)||[];
					var skills=ui.create.div('.characterskill',uiintro);
					if(lib.config.touchscreen){
						lib.setScroll(introduction);
						lib.setScroll(introduction2);
						lib.setScroll(skills);
					}

					if(lib.config.mousewheel){
						skills.onmousewheel=ui.click.mousewheel;
					}
					var clickSkill=function(e){
						while(introduction2.firstChild){
							introduction2.removeChild(introduction2.lastChild);
						}
						var current=this.parentNode.querySelector('.active');
						if(current){
							current.classList.remove('active');
						}
						this.classList.add('active');
						const skillNameSpan=document.createElement('span'),skillNameSpanStyle=skillNameSpan.style;
						skillNameSpanStyle.fontWeight='bold';
						const link=this.link,skillName=get.translation(link);
						skillNameSpan.innerHTML=skillName;
						const showSkillNamePinyin=lib.config.show_skillnamepinyin;
						if(showSkillNamePinyin!='doNotShow'&&skillName!='阵亡'){
							const ruby=document.createElement('ruby');
							ruby.appendChild(skillNameSpan);
							const leftParenthesisRP=document.createElement('rp');
							leftParenthesisRP.textContent='(';
							ruby.appendChild(leftParenthesisRP);
							const rt=document.createElement('rt');
							rt.innerHTML=showSkillNamePinyin=='showCodeIdentifier'?link:lib.translate[`${link}_rt`]||get.pinyin(skillName).join(' ');
							ruby.appendChild(rt);
							const rightParenthesisRP=document.createElement('rp');
							rightParenthesisRP.textContent=')';
							ruby.appendChild(rightParenthesisRP);
							const div=ui.create.div(introduction2);
							div.style.marginRight='5px';
							div.appendChild(ruby);
						}
						else{
							skillNameSpanStyle.marginRight='5px';
							introduction2.appendChild(skillNameSpan);
						}
						htmlParser.innerHTML=get.skillInfoTranslation(this.link);
						Array.from(htmlParser.childNodes).forEach(childNode=>introduction2.appendChild(childNode));
						var info=get.info(this.link);
						var skill=this.link;
						var playername=this.linkname;
						var skillnode=this;
						let derivations=info.derivation;
						if(derivations){
							if(typeof derivations=='string') derivations=[derivations];
							derivations.forEach(derivation=>{
								introduction2.appendChild(document.createElement('br'));
								introduction2.appendChild(document.createElement('br'));
								const derivationNameSpan=document.createElement('span'),derivationNameSpanStyle=derivationNameSpan.style;
								derivationNameSpanStyle.fontWeight='bold';
								const derivationName=get.translation(derivation);
								derivationNameSpan.innerHTML=derivationName;
								if(showSkillNamePinyin!='doNotShow'&&derivationName.length<=5&&derivation.indexOf('_faq')==-1){
									const ruby=document.createElement('ruby');
									ruby.appendChild(derivationNameSpan);
									const leftParenthesisRP=document.createElement('rp');
									leftParenthesisRP.textContent='(';
									ruby.appendChild(leftParenthesisRP);
									const rt=document.createElement('rt');
									rt.innerHTML=showSkillNamePinyin=='showCodeIdentifier'?derivation:lib.translate[`${derivation}_rt`]||get.pinyin(derivationName).join(' ');
									ruby.appendChild(rt);
									const rightParenthesisRP=document.createElement('rp');
									rightParenthesisRP.textContent=')';
									ruby.appendChild(rightParenthesisRP);
									const div=ui.create.div(introduction2);
									div.style.marginRight='5px';
									div.appendChild(ruby);
								}
								else{
									derivationNameSpanStyle.marginRight='5px';
									introduction2.appendChild(derivationNameSpan);
								}
								htmlParser.innerHTML=get.skillInfoTranslation(derivation);
								Array.from(htmlParser.childNodes).forEach(childNode=>introduction2.appendChild(childNode));
							});
						}
						if(info.alter){
							introduction2.appendChild(document.createElement('br'));
							introduction2.appendChild(document.createElement('br'));
							ui.create.div('.hrefnode.skillversion',introduction2);
							var skillversionnode=introduction2.querySelector('.hrefnode.skillversion');
							if(lib.config.vintageSkills.contains(skill)){
								skillversionnode.innerHTML='切换至新版';
							}
							else{
								skillversionnode.innerHTML='切换至旧版';
							}
							skillversionnode.listen(function(){
								if(lib.config.vintageSkills.contains(skill)){
									lib.config.vintageSkills.remove(skill);
									lib.translate[skill+'_info']=lib.translate[skill+'_info_alter'];
								}
								else{
									lib.config.vintageSkills.push(skill);
									lib.translate[skill+'_info']=lib.translate[skill+'_info_origin'];
								}
								game.saveConfig('vintageSkills',lib.config.vintageSkills);
								clickSkill.call(skillnode,'init');
							});
						}
						// if(e!=='init') game.trySkillAudio(this.link,playername);
						// 有bug,先用旧版
						if(lib.config.background_speak&&e!=='init'){
							var audioname=this.link;
							if(info.audioname2&&info.audioname2[playername]){
								audioname=info.audioname2[playername];
								info=lib.skill[audioname];
							}
							var audioinfo=info.audio;
							var that=this;
							var getIndex=function(i){
								if(typeof that.audioindex!='number'){
									that.audioindex=i;
								}
								that.audioindex++;
								if(that.audioindex>i){
									that.audioindex=1;
								}
								return that.audioindex;
							};
							if(typeof audioinfo=='string'){
								if(audioinfo.indexOf('ext:')==0){
									audioinfo=audioinfo.split(':');
									if(audioinfo.length==3){
										if(audioinfo[2]=='true'){
											game.playAudio('..','extension',audioinfo[1],audioname);
										}
										else{
											audioinfo[2]=parseInt(audioinfo[2]);
											if(audioinfo[2]){
												game.playAudio('..','extension',audioinfo[1],audioname+getIndex(audioinfo[2]));
											}
										}
									}
									return;
								}
								else{
									audioname=audioinfo;
									if(lib.skill[audioinfo]){
										audioinfo=lib.skill[audioinfo].audio;
									}
								}
							}
							else if(Array.isArray(audioinfo)){
								audioname=audioinfo[0];
								audioinfo=audioinfo[1];
							}
							if(typeof audioinfo=='number'){
								if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername;
								game.playAudio('skill',audioname+getIndex(audioinfo));
							}
							else if(typeof audioinfo=="object"&&"type" in audioinfo&&audioinfo.type=="direct"&&"files" in audioinfo){
								let audioFiles=audioinfo.files;
								if(typeof audioFiles=="object"){
									if(!Array.isArray(audioFiles)&&playername&&playername in audioFiles)audioFiles=audioFiles[playername];
									if(Array.isArray(audioFiles)){
										const length=audioFiles.length;
										game.playAudio(audioFiles[getIndex(length)-1]);
									}
								}
							}
							else if(audioinfo){
								if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername;
								game.playAudio('skill',audioname);
							}
							else if(true&&info.audio!==false){
								if(Array.isArray(info.audioname)&&info.audioname.contains(playername)) audioname=audioname+'_'+playername;
								game.playSkillAudio(audioname,getIndex(2));
							}
						}
					}
				}
				
				var initskill=false;
				for(var i=0;i<list.length;i++){
					if(!get.info(list[i])||get.info(list[i]).nopop) continue;
					if(!lib.translate[list[i]]||!lib.translate[list[i]+'_info']) continue;
					var skilltrans=get.translation(list[i]);
					if(skilltrans.startsWith('&nbsp;')){
						skilltrans=skilltrans.slice(6);
					}
					var current=ui.create.div('.menubutton.large',skills,clickSkill,skilltrans);
					current.link=list[i];
					current.linkname=name;
					if(!initskill){
						initskill=true;
						clickSkill.call(current,'init');
					}
				}

				uiintro.addEventListener(lib.config.touchscreen?'touchend':'click',ui.click.touchpop);
				layer.addEventListener(lib.config.touchscreen?'touchend':'click',clicklayer);
				ui.window.appendChild(layer);
			},
			intro:function(e){
				if(_status.dragged) return;
				_status.clicked=true;
				if(this.classList.contains('player')&&!this.name){
					return;
				}
				if(this.parentNode==ui.historybar){
					if(ui.historybar.style.zIndex=='22'){
						if(_status.removePop){
							if(_status.removePop(this)==false) return;
						}
						else{
							return;
						}
					}
					ui.historybar.style.zIndex=22;
				}
				var uiintro;
				if(this.classList.contains('card')&&this.parentNode&&
				this.parentNode.classList.contains('equips')&&get.is.phoneLayout()&&
				!get.is.mobileMe(this.parentNode.parentNode)){
					uiintro=get.nodeintro(this.parentNode.parentNode,false,e);
				}
				uiintro=uiintro||get.nodeintro(this,false,e);
				if(!uiintro) return;
				uiintro.classList.add('popped');
				uiintro.classList.add('static');
				ui.window.appendChild(uiintro);
				var layer=ui.create.div('.poplayer',ui.window);
				var clicklayer=function(e){
					if(_status.touchpopping) return;
					delete ui.throwEmotion;
					delete _status.removePop;
					uiintro.delete();
					this.remove();
					ui.historybar.style.zIndex='';
					delete _status.currentlogv;
					if(!ui.arena.classList.contains('menupaused')&&!uiintro.noresume) game.resume2();
					if(e&&e.stopPropagation) e.stopPropagation();
					if(uiintro._onclose){
						uiintro._onclose();
					}
					return false;
				}
				layer.addEventListener(lib.config.touchscreen?'touchend':'click',clicklayer);
				if(!lib.config.touchscreen) layer.oncontextmenu=clicklayer;
				if(this.parentNode==ui.historybar&&lib.config.touchscreen){
					var rect=this.getBoundingClientRect();
					e={clientX:0,clientY:rect.top+30};
				}
				lib.placePoppedDialog(uiintro,e);
				if(this.parentNode==ui.historybar){
					if(lib.config.show_history=='right'){
						uiintro.style.left=(ui.historybar.offsetLeft-230)+'px';
					}
					else{
						uiintro.style.left=(ui.historybar.offsetLeft+60)+'px';
					}
				}
				uiintro.style.zIndex=21;
				var clickintro=function(){
					if(_status.touchpopping) return;
					delete _status.removePop;
					layer.remove();
					this.delete();
					ui.historybar.style.zIndex='';
					delete _status.currentlogv;
					if(!ui.arena.classList.contains('menupaused')&&!uiintro.noresume) game.resume2();
					if(uiintro._onclose){
						uiintro._onclose();
					}
				};
				var currentpop=this;
				_status.removePop=function(node){
					if(node==currentpop) return false;
					layer.remove();
					uiintro.delete();
					delete _status.removePop;
					return true;
				};
				if(uiintro.clickintro){
					uiintro.listen(function(){
						_status.clicked=true;
					});
					uiintro._clickintro=clicklayer;
				}
				else if(!lib.config.touchscreen){
					uiintro.addEventListener('mouseleave',clickintro);
					uiintro.addEventListener('click',clickintro);
				}
				else if(uiintro.touchclose){
					uiintro.listen(clickintro);
				}
				uiintro._close=clicklayer;

				game.pause2();
				return uiintro;
			},
			intro2:function(){
				if(ui.intro){
					ui.intro.close();
					if(ui.intro.source==this){
						delete ui.intro;
						ui.control.show();
						game.resume2();
						return;
					}
				}
			},
			auto:function(){
				if(!ui||!ui.auto||ui.auto.classList.contains('hidden')&&arguments[0]!=='forced') return;
				if(_status.paused2) return;
				ui.click.shortcut(false);
				if(!_status.auto){
					_status.auto=true;
					ui.auto.classList.add('glow');
					ui.arena.classList.add('auto');

					if(_status.imchoosing&&_status.paused){
						if(ui.confirm) ui.confirm.close();
						ui.control.hide();
						if(_status.event.switchToAuto){
							_status.event.switchToAuto();
						}
						else{
							if(_status.paused&&_status.imchoosing){
								game.uncheck();
								_status.event.redo();
							}
						}
						game.resume();
					}
					else if(_status.event.switchToAuto){
						_status.event.switchToAuto();
					}
					if(game.online){
						game.send('auto');
					}
					else if(_status.connectMode){
						game.broadcastAll(function(player){
							player.setNickname(player.nickname+' - 托管');
						},game.me);
					}
				}
				else{
					if(game.notMe) return;
					ui.control.show();
					_status.auto=false;
					ui.auto.classList.remove('glow');
					ui.arena.classList.remove('auto');

					if(game.online){
						game.send('unauto');
					}
					else if(_status.connectMode){
						game.broadcastAll(function(player){
							player.setNickname(player.nickname);
						},game.me);
					}
				}
			},
			wuxie:function(){
				if(this.classList.contains('hidden')) return;
				this.classList.toggle('glow');
				if(this.classList.contains('glow')&&_status.event.type=='wuxie'&&
				_status.event.isMine()&&ui.confirm&&_status.imchoosing){
					ui.click.cancel(ui.confirm.lastChild);
				}
			},
			tempnowuxie:function(){
				if(this.classList.contains('hidden')) return;
				this.classList.toggle('glow');
				if(this.classList.contains('glow')&&_status.event.type=='wuxie'&&
				_status.event.isMine()&&ui.confirm&&_status.imchoosing){
					var triggerevent=_status.event.getTrigger();
					if(triggerevent&&this._origin==triggerevent.parent.id){
						if(triggerevent.targets&&triggerevent.num==triggerevent.targets.length-1){
							this.close();
						}
					}
					ui.click.cancel(ui.confirm.lastChild);
				}
			},
			pause:function(){
				if(_status.paused2||_status.pausing||_status.nopause||!ui.pause) return;
				if(!_status.video){
					if(ui.pause.classList.contains('hidden')) return;
					if(!_status.gameStarted) return;
				}
				ui.system.hide();
				game.pause2();
				var node=ui.create.pause();
				if(!node) return;
				node.animate('start');
				ui.sidebar3.innerHTML='';
				if(lib.config.show_discardpile){
					for(var i=0;i<ui.discardPile.childNodes.length;i++){
						var div=ui.create.div(ui.sidebar3);
						div.innerHTML=get.translation(ui.discardPile.childNodes[i]);
						ui.sidebar3.insertBefore(div,ui.sidebar3.firstChild);
					}
				}
				node.appendChild(ui.sidebar);
				node.appendChild(ui.sidebar3);
				ui.historybar.classList.add('paused');
				ui.arena.classList.add('paused');
				ui.window.classList.add('touchinfohidden');
				ui.time.hide();
				if(game.onpause){
					game.onpause();
				}
			},
			resume:function(e){
				if(_status.pausing) return;
				if(_status.dragged) return;
				if(_status.clicked) return;
				this.delete();
				ui.system.show();
				ui.time.show();
				ui.historybar.classList.remove('paused');
				ui.arena.classList.remove('paused');
				ui.window.classList.remove('touchinfohidden');
				game.resume2();
				e.stopPropagation();
				if(game.onresume){
					game.onresume();
				}
				return false;
			},
			config:function(){
				if(!ui.click.configMenu) return;
				if(_status.paused2) _status.config2=false;
				else _status.config2=true;

				_status.clicked=true;
				game.pause2();
				ui.click.configMenu();
				ui.system1.classList.remove('shown');
				ui.system2.classList.remove('shown');
			},
			swap:function(){
				if(_status.dragged) return;
				if(this.classList.contains('dead')) return;
				if(_status.over) return;
				if(ui.auto) ui.auto.show();
				if(ui.wuxie) ui.wuxie.show();
				game.swapPlayer(this);
			},
			mousewheel:function(evt){
				if(this.firstChild&&this.firstChild.classList.contains('handcards')&&
					!this.classList.contains('scrollh')) return;
				var node=this;
				var num=this._scrollnum||6;
				var speed=this._scrollspeed||16;
				clearInterval(node.interval);
				if(evt.detail > 0 || evt.wheelDelta < 0){
					node.interval=setInterval(function(){
						if(num--&&Math.abs(node.scrollLeft+node.clientWidth-node.scrollWidth)>0){
							node.scrollLeft +=speed;
						}
						else{
							clearInterval(node.interval);
						}
					},16);
				}
				else{
					node.interval=setInterval(function(){
						if(num--&&node.scrollLeft>0){
							node.scrollLeft -=speed;
						}
						else{
							clearInterval(node.interval);
						}
					},16);
				}
			},
			touchStart:function(e){
				this.startX=e.touches[0].clientX/game.documentZoom;
				this.startY=e.touches[0].clientY/game.documentZoom;
				_status.dragged=false;
			},
			dialogtouchStart:function(e){
				ui.click.touchStart.call(this,e);
				_status.dialogtouched=true;
			},
			touchScroll:function(e) {
				if(_status.mousedragging) return;
				if(_status.draggingtouchdialog) return;
				if(!_status.dragged){
					if (Math.abs(e.touches[0].clientX/game.documentZoom - this.startX) > 10 ||
						Math.abs(e.touches[0].clientY/game.documentZoom - this.startY) > 10) {
						_status.dragged=true;
					}
				}
				if((this==ui.handcards1Container||this==ui.handcards2Container)&&!this.classList.contains('scrollh')){
					e.preventDefault();
				}
				else if(lib.device=='ios'&&this.scrollHeight<=this.offsetHeight+5&&this.scrollWidth<=this.offsetWidth+5){
					e.preventDefault();
				}
				else{
					delete _status._swipeorigin;
					e.stopPropagation();
				}
			},
			autoskill:function(bool,node){
				var list=lib.config.autoskilllist;
				if(bool){
					list.remove(node.link);
				}
				else{
					list.add(node.link);
				}
				game.saveConfig('autoskilllist',list);
			},
			skillbutton:function(){
				this.func(this.link);
			},
			autoskill2:function(e){
				this.classList.toggle('on');
				var list=[];
				if(lib.skill[this.link].frequent){
					list.push(this.link);
				}
				if(lib.skill[this.link].subfrequent){
					for(var i=0;i<lib.skill[this.link].subfrequent.length;i++){
						list.push(this.link+'_'+lib.skill[this.link].subfrequent[i]);
					}
				}
				for(var i=0;i<list.length;i++){
					if(this.classList.contains('on')){
						lib.config.autoskilllist.remove(list[i]);
					}
					else{
						lib.config.autoskilllist.add(list[i]);
					}
				}
				game.saveConfig('autoskilllist',lib.config.autoskilllist);
				ui.click.touchpop();
				e.stopPropagation();
			},
			hiddenskill:function(e){
				this.classList.toggle('on');
				var hidden=lib.skill[this.link].preHidden;
				if(Array.isArray(hidden)){
					if(this.classList.contains('on')){
						_status.prehidden_skills.removeArray(hidden);
					}
					else{
						_status.prehidden_skills.addArray(hidden);
					}
				}
				if(this.classList.contains('on')){
					_status.prehidden_skills.remove(this.link);
				}
				else{
					_status.prehidden_skills.add(this.link);
				}
				ui.click.touchpop();
				e.stopPropagation();
			},
			// forcetouch:function(){
			// 	if(_status.force||_status.dragged){
			// 		clearInterval(_status.forcetouchinterval);
			// 		delete _status.forcetouchinterval;
			// 		return;
			// 	}
			// 	window.ForceTouch.getForceTouchData(function(ForceTouchData){
			// 		if(ForceTouchData.touches[0]){
			// 			var force = parseFloat(ForceTouchData.touches[0].force);
			// 			if(force > 0.2){
			// 				_status.force=true;
			// 				var taptic=false;
			// 				if(_status.longpressing){
			// 					delete _status.longpressing._waitingfordrag;
			// 					ui.click.touchpop();
			// 					ui.click.longpresscallback.call(_status.longpressing);
			// 					taptic=true;
			// 				}
			// 				else if(!_status.forceright){
			// 					_status.forceright=true;
			// 					setTimeout(function(){
			// 						_status.forceright=false;
			// 					},600);
			// 					if(_status.mousedragging){
			// 						_status.mousedragging=null;
			// 						_status.mouseleft=false;
			// 						_status.mousedragorigin=null;
			// 						_status.dragstatuschanged=false;
			// 						game.uncheck();
			// 						game.check();
			// 					}
			// 					switch(lib.config.pressure_click){
			// 						case 'pause':ui.click.pause();break;
			// 						case 'auto':ui.click.auto();break;
			// 						case 'config':ui.click.config();break;
			// 					}
			// 					taptic=true;
			// 				}
			// 				if(taptic&&lib.config.pressure_taptic){
			// 					if(window.TapticEngine){
			// 						window.TapticEngine.generateTapticFeedback();
			// 					}
			// 					else{
			// 						game.vibrate(50);
			// 					}
			// 				}
			// 			}
			// 		}
			// 	});
			// },
			// pressurepause:function(force,event){
			// 	if(!_status.force&&!_status.mousedragging&&force>=0.5&&!_status.forceright){
			// 		_status.force=true;
			// 		_status.forceright=true;
			// 		setTimeout(function(){
			// 			_status.forceright=false;
			// 		},600);
			// 		switch(lib.config.pressure_click){
			// 			case 'pause':ui.click.pause();break;
			// 			case 'auto':ui.click.auto();break;
			// 			case 'config':ui.click.config();break;
			// 		}
			// 	}
			// },
			// rightpressure:function(force, event){
			// 	if(force>0){
			// 		_status.force=true;
			// 	}
			// 	if(force>=0.5){
			// 		if(_status.mousedragging){
			// 			_status.mousedragging=null;
			// 			_status.mouseleft=false;
			// 			_status.mousedragorigin=null;
			// 			_status.dragstatuschanged=false;
			// 			game.uncheck();
			// 			game.check();
			// 		}
			// 		ui.click.rightplayer.call(this,event);
			// 		_status.clickedplayer=false;
			// 	}
			// },
			rightplayer:function(e){
				if(this._nopup) return false;
				if(_status.clickedplayer){
					return false;
				}

				if(this._mouseenterdialog&&this._mouseenterdialog.parentNode){
					this._mouseenterdialog.delete();
				}
				else{
					ui.click.intro.call(this,e);
				}
				_status.clickedplayer=true;
				_status.clicked=false;
				ui.click.longpresscancel.call(this);
				return false;
			},
			right:function(e){
				if(window.inSplash) return false;
				if(lib.config.touchscreen) return;
				if(_status.noright){
					_status.noright=false;
					return false;
				}
				if(_status.clickedplayer){
					_status.clickedplayer=false;
					return;
				}
				game.closePopped();
				switch(lib.config.right_click){
					case 'shortcut':ui.click.shortcut();break;
					case 'pause':ui.click.pause();break;
					case 'auto':ui.click.auto();break;
					case 'config':ui.click.config();break;
				}
				e.preventDefault();
				return false;
			}
		},
		selected:{
			buttons:[],cards:[],targets:[]
		},
		clear:function(){
			game.addVideo('uiClear');
			var thrown=document.getElementsByClassName('thrown');
			var nodes=[];
			var i;
			for(i=0;i<thrown.length;i++){
				nodes.push(thrown[i]);
			}
			for(i=0;i<nodes.length;i++){
				if(!nodes[i].fixed) nodes[i].delete();
			}
		},
		updatec:function(){
			if(_status.noupdatec) return;
			var length=0,minoffset=-Infinity;
			var controls=[];
			var widths=[];
			var leftwidths=[];
			var add=function(node,first){
				var thiswidth=parseInt(node.style.width);
				if(thiswidth){
					thiswidth+=8;
					length+=thiswidth;
					if(first){
						leftwidths.push(thiswidth);
					}
					else{
						widths.push(thiswidth);
					}
				}
				else{
					length+=node.offsetWidth;
					if(first){
						leftwidths.push(node.offsetWidth);
					}
					else{
						widths.push(node.offsetWidth);
					}
				}
				if(first){
					controls.unshift(node);
				}
				else{
					controls.push(node);
				}
			}
			widths=leftwidths.concat(widths);
			var staylefts=[];
			for(var i=0;i<ui.control.childNodes.length;i++){
				if(ui.control.childNodes[i].classList.contains('removing')) continue;
				if(lib.config.wuxie_right&&ui.control.childNodes[i].stayleft){
					staylefts.push(ui.control.childNodes[i]);
				}
				else{
					add(ui.control.childNodes[i]);
				}
			}
			if(staylefts.length){
				var fullwidth=0;
				var fullright=(game.layout=='long'||game.layout=='long2'||game.chess||(game.layout!='nova'&&parseInt(ui.arena.dataset.number)<=5));
				for(var i=0;i<widths.length;i++){
					fullwidth+=widths[i]+6;
					if(get.is.phoneLayout()) fullwidth+=6;
				}
				fullwidth/=2;
				var currentLeft=0;
				for(var stayleft of staylefts){
					stayleft.currentLeft=currentLeft;
					fullwidth+=stayleft.offsetWidth;
					currentLeft+=stayleft.offsetWidth;
					if(get.is.phoneLayout()){
						fullwidth+=18;
						currentLeft+=18;
					}
					else{
						fullwidth+=12;
						currentLeft+=12;
					}
				}
				if(fullright){
					fullwidth+=124;
					if((game.layout=='long2'||game.layout=='nova')&&ui.arena.dataset.number=='8'&&get.mode()!='boss'){
						fullwidth+=game.me.getLeft();
					}
				}
				else{
					fullwidth+=154;
				}
				for(var stayleft of staylefts){
					if(game.layout!='default'){
						var current_offset=stayleft._offset;
						if(fullright){
							stayleft._offset=Math.ceil(-ui.arena.offsetWidth/2)+135;
							if((game.layout=='long2'||game.layout=='nova')&&ui.arena.dataset.number=='8'&&get.mode()!='boss'){
								stayleft._offset+=game.me.getLeft();
							}
						}
						else{
							stayleft._offset=Math.ceil(-ui.arena.offsetWidth/2)+165;
						}
						stayleft._offset+=stayleft.currentLeft;
						
						if(current_offset!=stayleft._offset){
							stayleft.animate('controlpressdownx',500);
							stayleft.style.transform='translateX('+stayleft._offset+'px)';
						}
					}
					else{
						add(stayleft,true);
					}
				}
				if(staylefts.length&&controls.length){
					var last=staylefts[staylefts.length-1];
					minoffset=last._offset+last.offsetWidth+(get.is.phoneLayout()?18:12);
				}
			}
			if(!controls.length) return;
			var offset=-length/2;
			if(minoffset>offset) offset=minoffset;
			var control=controls.shift();
			if(control._offset!=offset){
				control.animate('controlpressdownx',500);
				control.style.transform='translateX('+offset+'px)';
				control._offset=offset;
			}
			while(controls.length){
				var control=controls.shift();
				var width=widths.shift();
				offset+=width+6;
				if(get.is.phoneLayout()){
					offset+=6;
				}
				if(control._offset!=offset){
					control.animate('controlpressdownx',500);
					control.style.transform='translateX('+offset+'px)';
					control._offset=offset;
				}
			}
		},
		updatex:function(){
			ui.update.apply(this,arguments);
			ui.updatehl();
			for(var i=0;i<lib.onresize.length;i++){
				lib.onresize[i]();
			}
			var cfg=game.documentZoom/game.deviceZoom;
			ui.updated();
			game.documentZoom=cfg*game.deviceZoom;
			ui.updatez();
			delete ui._updatexr;
		},
		updatexr:function(){
			if(ui._updatexr){
				clearTimeout(ui._updatexr);
			}
			ui._updatexr=setTimeout(ui.updatex,500);
		},
		updatejm:function(player,nodes,start,inv){
			if(typeof start!='number'){
				start=0;
			}
			var str;
			if(get.is.mobileMe(player)||game.layout=='default'||player.classList.contains('linked')){
				str='translateX(';
				if(inv){
					str+='-';
				}
			}
			else{
				str='translateY(';
			}
			var num=0;
			for(var i=0;i<nodes.childElementCount;i++){
				var node=nodes.childNodes[i];
				if(i<start){
					node.style.transform='';
				}
				else if(node.classList.contains('removing')){
					start++;
				}
				else{
					ui.refresh(node);
					node.classList.remove('drawinghidden');
					node._transform=str+((i-start)*28)+'px)';
					node.style.transform=node._transform;
				}
			}
		},
		updatem:function(player){
			if(player){
				var start=0;
				if(!player.classList.contains('linked2')||!ui.arena.classList.contains('nolink')){
					start=1;
				}
				ui.updatejm(player,player.node.marks,start,get.is.mobileMe(player));
			}
			else{
				for(var i=0;i<game.players.length;i++){
					ui.updatem(game.players[i]);
				}
			}
		},
		updatej:function(player){
			if(player){
				ui.updatejm(player,player.node.judges);
			}
			else{
				for(var i=0;i<game.players.length;i++){
					ui.updatej(game.players[i]);
				}
			}
		},
		updatehl:function(){
			if(!game.me) return;
			if(!ui.handcards1Container||!ui.handcards2Container) return;
			if(!ui.handcards1Container.childNodes.length) return;
			var hs1=[],hs2=[];
			for(var i=0;i<ui.handcards1Container.firstChild.childElementCount;i++){
				if(!ui.handcards1Container.firstChild.childNodes[i].classList.contains('removing')){
					hs1.push(ui.handcards1Container.firstChild.childNodes[i]);
				}
			}
			for(var i=0;i<ui.handcards2Container.firstChild.childElementCount;i++){
				if(!ui.handcards2Container.firstChild.childNodes[i].classList.contains('removing')){
					hs2.push(ui.handcards2Container.firstChild.childNodes[i]);
				}
			}
			var offset1,offset12=0;
			if(!lib.config.fold_card){
				offset1=112;
				ui.handcards1Container.classList.add('scrollh');
			}
			else{
				offset1=Math.min(112,(ui.handcards1Container.offsetWidth-128)/(hs1.length-1));
				if(hs1.length>1&&offset1<32){
					offset1=32;
					ui.handcards1Container.classList.add('scrollh');
				}
				else{
					ui.handcards1Container.classList.remove('scrollh');
				}
			}
			if(offset1<100){
				offset12=100-offset1;
			}
			for(var i=0;i<hs1.length;i++){
				hs1[i].style.transform='translateX('+(i*offset1)+'px)';
				hs1[i]._transform='translateX('+(i*offset1)+'px)';
				ui.refresh(hs1[i]);
				hs1[i].classList.remove('drawinghidden');
				if(offset12>40){
					offset12=90-hs1[i].node.info.offsetWidth;
					hs1[i].node.info.querySelector('span').style.display='none';
					if(hs1[i].node.name.classList.contains('long')){
						hs1[i].node.name.style.transform='translateY(16px)  scale(0.85)';
						hs1[i].node.name.style.transformOrigin='top left';
					}
					else{
						hs1[i].node.name.style.transform='translateY(16px)';
					}
					hs1[i].node.info.style.transform='translateX(-'+offset12+'px) translateY(-3px)';
				}
				else{
					hs1[i].node.info.querySelector('span').style.display='';
					hs1[i].node.name.style.transform='';
					hs1[i].node.name.style.transformOrigin='';
					hs1[i].node.info.style.transform='translateX(-'+offset12+'px)';
				}
			}
			ui.handcards1Container.firstChild.style.width=(offset1*(hs1.length-1)+118)+'px';

			var offset2,offset22=0;
			if(!lib.config.fold_card){
				offset2=112;
				ui.handcards2Container.classList.add('scrollh');
			}
			else{
				offset2=Math.min(112,(ui.handcards2Container.offsetWidth-128)/(hs2.length-1));
				if(hs2.length>1&&offset2<32){
					offset2=32;
					ui.handcards2Container.classList.add('scrollh');
				}
				else{
					ui.handcards2Container.classList.remove('scrollh');
				}
			}
			if(offset2<100){
				offset22=100-offset2;
			}
			for(var i=0;i<hs2.length;i++){
				hs2[i].style.transform='translateX('+(i*offset2)+'px)';
				hs2[i]._transform='translateX('+(i*offset2)+'px)';
				ui.refresh(hs2[i]);
				hs2[i].classList.remove('drawinghidden');
				if(offset22>40){
					offset22=90-hs2[i].node.info.offsetWidth;
					hs2[i].node.info.querySelector('span').style.display='none';
					if(hs2[i].node.name.classList.contains('long')){
						hs2[i].node.name.style.transform='translateY(16px)  scale(0.85)';
						hs2[i].node.name.style.transformOrigin='top left';
					}
					else{
						hs2[i].node.name.style.transform='translateY(16px)';
					}
					hs2[i].node.info.style.transform='translateX(-'+offset22+'px) translateY(-3px)';
				}
				else{
					hs2[i].node.info.querySelector('span').style.display='';
					hs2[i].node.name.style.transform='';
					hs2[i].node.name.style.transformOrigin='';
					hs2[i].node.info.style.transform='translateX(-'+offset22+'px)';
				}
			}
			ui.handcards2Container.firstChild.style.width=(offset2*(hs2.length-1)+118)+'px';
		},
		updateh:function(compute){
			if(!game.me) return;
			if(!ui.handcards1Container) return;
			if(lib.config.low_performance){
				if(compute){
					ui.updatehl();
					setTimeout(ui.updatehl,1000);
				}
				return;
			}
			if(compute){
				ui.handcards1Container._handcardsWidth=ui.handcards1Container.offsetWidth;
				ui.handcards2Container._handcardsWidth=ui.handcards2Container.offsetWidth;
			}
			ui.updatehx(game.me.node.handcards1);
			ui.updatehx(game.me.node.handcards2);
		},
		updatehx:function(node){
			var width=node.parentNode._handcardsWidth;
			var num=node.childElementCount-node.getElementsByClassName('removing').length;
			node.classList.remove('fold0');
			node.classList.remove('fold1');
			node.classList.remove('fold2');
			node.classList.remove('fold3');
			if(num*78+40>=width){
				// node.dataset.fold=3;
				node.classList.add('fold3');
			}
			else if(num*93+25>=width){
				// node.dataset.fold=2;
				node.classList.add('fold2');
			}
			else if(num*112+6>=width){
				// node.dataset.fold=1;
				node.classList.add('fold1');
			}
			else{
				// node.dataset.fold=0;
				node.classList.add('fold0');
			}
		},
		updated:function(){
			if (document.documentElement.offsetWidth<900 || document.documentElement.offsetHeight < 500) {
				game.deviceZoom=Math.min(
					Math.round(document.documentElement.offsetWidth/98)/10,
					Math.round(document.documentElement.offsetHeight/50)/10
				);
			}
			else {
				game.deviceZoom=1;
			}
		},
		updatez:function(){
			var width=document.documentElement.offsetWidth;
			var height=document.documentElement.offsetHeight;
			var zoom=game.documentZoom;
			if(zoom!=1){
				document.body.style.width=Math.round(width/zoom)+'px';
				document.body.style.height=Math.round(height/zoom)+'px';
				document.body.style.transform='scale('+(Math.floor(zoom*100)/100)+')';
			}
			else{
				document.body.style.width=width+'px';
				document.body.style.height=height+'px';
				document.body.style.transform='';
			}
		},
		update:function(){
			for(var i=0;i<ui.updates.length;i++){
				ui.updates[i]();
			}
			if(ui.dialog&&!ui.dialog.classList.contains('noupdate')){
				if(game.chess){
					if(ui.dialog.content.scrollHeight<240&&(!ui.dialog.buttons||!ui.dialog.buttons.length)&&!ui.dialog.forcebutton){
						ui.dialog.style.height=ui.dialog.content.offsetHeight+'px';
						ui.dialog.classList.add('slim');
					}
					else{
						ui.dialog.style.height='';
						ui.dialog.classList.remove('slim');
					}
				}
				else{
					if((!ui.dialog.buttons||!ui.dialog.buttons.length)&&!ui.dialog.forcebutton&&ui.dialog.classList.contains('fullheight')==false&&get.mode()!='stone'){
						ui.dialog.classList.add('nobutton');
						if(ui.dialog.content.offsetHeight<240){
							if(!ui.dialog._heightset){
								ui.dialog._heightset=ui.dialog.style.height||true;
							}
							ui.dialog.style.height=ui.dialog.content.offsetHeight+'px';
							if(lib.config.show_log!='off'){
								ui.dialog.classList.add('scroll1');
								ui.dialog.classList.add('scroll2');
								return;
							}
						}
						else{
							if(typeof ui.dialog._heightset=='string'){
								ui.dialog.style.height=ui.dialog._heightset;
							}
							else if(ui.dialog._heightset){
								ui.dialog.style.height='';
							}
							delete ui.dialog._heightset;
						}
					}
					else{
						if(typeof ui.dialog._heightset=='string'){
							ui.dialog.style.height=ui.dialog._heightset;
						}
						else if(ui.dialog._heightset){
							ui.dialog.style.height='';
						}
						delete ui.dialog._heightset;
						ui.dialog.classList.remove('nobutton');
					}
				}
				var height1=ui.dialog.content.offsetHeight;
				var height2=ui.dialog.contentContainer.offsetHeight;
				if(game.chess){
					if(height1<240){
						ui.dialog.style.height=height1+'px';
					}
				}
				else{
					if(!ui.dialog.forcebutton&&!ui.dialog._scrollset&&(height1<=190||(height2>=height1&&height2>=210))){
						ui.dialog.classList.remove('scroll1');
						ui.dialog.classList.remove('scroll2');
					}
					else{
						ui.dialog.classList.add('scroll1');
						ui.dialog.classList.add('scroll2');
						if(game.layout!='default'){
							ui.dialog.style.height=Math.min(height1,((game.layout=='long2'||game.layout=='nova')&&ui.arena.classList.contains('choose-character'))?380:350)+'px';
							ui.dialog._scrollset=true;
						}
					}
					if(game.layout=='long2'||game.layout=='nova'){
						if(height1+240>=ui.arena.offsetHeight){
							ui.dialog.classList.add('scroll3');
						}
						else{
							ui.dialog.classList.remove('scroll3');
						}
					}
				}
			}
		},
		recycle:function(node,key){
			if(!ui._recycle) ui._recycle={};
			if(typeof node=='string'){
				return ui._recycle[node]
			}
			ui._recycle[key]=node;
		},
	};
	const get={
		//Generate an object URL from the Base64-encoded octet stream
		//从Base64编码的八位字节流生成对象URL
		objectURL:octetStream=>{
			const objectURLMap=lib.objectURL;
			if(objectURLMap.has(octetStream)) return objectURLMap.get(octetStream);
			const objectURL=URL.createObjectURL(new Blob([Uint8Array.from(atob(octetStream.replace(/^data:[\s\S]*\/[\s\S]*;base64,/,'')),character=>character.charCodeAt())]));
			objectURLMap.set(octetStream,objectURL);
			return objectURL;
		},
		//Get the card name length
		//获取此牌的字数
		cardNameLength:(card,player)=>{
			const actualCardName=lib.actualCardName,name=get.translation(typeof card=='string'?card:get.name(card,player));
			return (actualCardName.has(name)?actualCardName.get(name):name).length;
		},
		//Yingbian
		//应变
		//Get the Yingbian conditions (of the card)
		//获取(此牌的)应变条件
		yingbianConditions:card=>get.complexYingbianConditions(card).concat(get.simpleYingbianConditions(card)),
		complexYingbianConditions:card=>{
			const complexYingbianConditions=Array.from(lib.yingbian.condition.complex.keys());
			return card?complexYingbianConditions.filter(value=>get.cardtag(card,`yingbian_${value}`)):complexYingbianConditions;
		},
		simpleYingbianConditions:card=>{
			const simpleYingbianConditions=Array.from(lib.yingbian.condition.simple.keys())
			return card?simpleYingbianConditions.filter(value=>get.cardtag(card,`yingbian_${value}`)):simpleYingbianConditions;
		},
		//Get the Yingbian effects (of the card)
		//获取(此牌的)应变效果
		yingbianEffects:card=>{
			const yingbianEffects=Array.from(lib.yingbian.effect.keys());
			return card?yingbianEffects.filter(value=>get.cardtag(card,`yingbian_${value}`)):yingbianEffects;
		},
		//Get the default Yingbian effect of the card
		//获取此牌的默认应变效果
		defaultYingbianEffect:card=>{
			const info=get.info(card);
			return info&&info.defaultYingbianEffect||null;
		},
		//优先度判断
		priority:function(skill){
			const info=get.info(skill);
			if(!info) return 0;
			if(info.hasOwnProperty('_priority')) return info._priority;
			let priority=0;
			if(info.priority){
				priority=info.priority*100;
			}
			if(info.silent){
				priority++;
			}
			if(info.equipSkill) priority-=25;
			if(info.cardSkill) priority-=50;
			if(info.ruleSkill) priority-=75;
			info._priority=priority;
			return priority;
		},
		//新装备栏相关
		//获取一张装备牌实际占用的装备栏(君曹操六龙)
		//用法同get.subtype,返回数组
		subtypes:function(obj,player){
			if(typeof obj=='string') obj={name:obj};
			if(typeof obj!='object') return;
			var name=get.name(obj,player);
			if(!lib.card[name]) return [];
			if(lib.card[name].subtypes) return get.copy(lib.card[name].subtypes);
			else if(lib.card[name].subtype) return [lib.card[name].subtype];
			return [];
		},
		//装备栏 END
		pinyin:(chinese,withTone)=>{
			const pinyinUtilx=window.pinyinUtilx;
			if(!pinyinUtilx) return [];
			const pinyins=lib.pinyins;
			if(pinyins){
				const pinyin=pinyins[chinese];
				if(Array.isArray(pinyin)) return withTone===false?pinyin.map(pinyinUtilx.removeTone):pinyin.slice();
			}
			return pinyinUtilx.getPinyin(chinese,null,withTone,true);
		},
		yunmu:function(str){
			//部分整体认读音节特化处理
			const util=window.pinyinUtilx;
			if(util&&lib.pinyins._metadata.zhengtirendu.contains(util.removeTone(str))){
				return '-'+str[str.length-1];
			}
			//排除声母
			for(let i of lib.pinyins._metadata.shengmu){
				if(str.startsWith(i)){
					str=str.slice(i.length);
					if(str[0]=='u'&&lib.pinyins._metadata.special_shengmu.contains(i)) str='ü'+str.slice(1);
					break;
				}
			}
			//排除介母
			if(str.length>0){
				for(let i in lib.pinyins._metadata.feijiemu){
					if(str[0]==i){
						let goon=false;
						for(let j of lib.pinyins._metadata.feijiemu[i]){
							if(str.startsWith(j)) goon=true;
						}
						if(!goon) str=str.slice(1);
						break;
					}
				}
			}
			return str;
		},
		//用于将参数转换为字符串,作为缓存的key。
		paramToCacheKey:function(){
			var str = "";
			for(var arg of arguments){
				if(arg === null || arg === undefined){
					str += (arg + "-");
					continue;
				}
				if(arg.playerid){
					str += "p:"+arg.playerid;
				}else if(arg.cardid){
					str += "c:"+arg.cardid;
				}else if(arg.name){
					str += "n:"+arg.name;
				}else{
					str += "s:"+arg;
				}
				str+="-";
			}
			return str;
		},
		yunjiao:function(str){
			const util=window.pinyinUtilx;
			if(util) str=util.removeTone(str)
			if(lib.pinyins._metadata.zhengtirendu.contains(str)){
				str=('-'+str[str.length-1]);
			}
			else{
				for(let i of lib.pinyins._metadata.shengmu){
					if(str.startsWith(i)){
						str=str.slice(i.length);
						if(str[0]=='u'&&lib.pinyins._metadata.special_shengmu.contains(i)) str='ü'+str.slice(1);
						break;
					}
				}
			}
			for(let i in lib.pinyins._metadata.yunjiao){
				if(lib.pinyins._metadata.yunjiao[i].contains(str)) return i;
			}
			return null;
		},
		skillCategoriesOf:function(skill,player){
			var list=[],info=get.info(skill);
			if(!info) return list;
			if(get.is.locked(skill,player)) list.add('锁定技');
			if(info.zhuSkill) list.add('主公技');
			if(info.limited) list.add('限定技');
			if(info.juexingji) list.add('觉醒技');
			if(info.zhuanhuanji) list.add('转换技');
			if(info.hiddenSkill) list.add('隐匿技');
			if(info.clanSkill) list.add('宗族技');
			if(info.groupSkill) list.add('势力技');
			if(info.dutySkill) list.add('使命技');
			if(info.chargeSkill) list.add('蓄力技');
			if(info.zhenfa) list.add('阵法技');
			if(info.mainSkill) list.add('主将技');
			if(info.viceSkill) list.add('副将技');
			if(info.lordSkill) list.add('君主技');
			if(info.chargingSkill) list.add('蓄能技');
			if(info.charlotte) list.add('Charlotte');
			if(info.sunbenSkill) list.add('昂扬技');
			if(info.categories) list.addArray(info.categories(skill,player));
			return list;
		},
		numOf:function(obj,item){
			var num=0;
			for(var i=0;i<obj.length;i++){
				if(obj[i]==item) num++;
			}
			return num;
		},
		connectNickname:function(){
			return typeof lib.config.connect_nickname=='string'?(lib.config.connect_nickname.slice(0,12)):'无名玩家';
		},
		zhinangs:function(filter){
			var list=(_status.connectMode?lib.configOL:lib.config).zhinang_tricks;
			if(!list||!list.filter||!list.length) return get.inpile('trick','trick').randomGets(3);
			if(filter===false) return list.slice(0);
			list=list.filter(function(i){
				return lib.inpile.contains(i);
			});
			if(list.length) return list;
			return get.inpile('trick','trick').randomGets(3);
		},
		sourceCharacter:function(str){
			if(str){
				for(var i in lib.characterReplace){
					if(lib.characterReplace[i].contains(str)) return i;
				}
			}
			return str;
		},
		isLuckyStar:function(player){
			if(player&&player.hasSkillTag('luckyStar')) return true;
			if(_status.connectMode) return false;
			return (!player||player==game.me||player.isUnderControl())&&lib.config.lucky_star==true;
		},
		infoHp:function(hp){
			if(typeof hp=='number') return hp;
			else if(typeof hp=='string'&&hp.includes('/')){
				return parseInt(hp.split('/')[0]);
			}
			return 0;
		},
		infoMaxHp:function(hp){
			if(typeof hp=='number') return hp;
			else if(typeof hp=='string'&&hp.includes('/')){
				return parseInt(hp.split('/')[1]);
			}
			return 0;
		},
		infoHujia:function(hp){
			if(typeof hp=='string'&&hp.includes('/')){
				var splited=hp.split('/');
				if(splited.length>2) return parseInt(splited[2]);
			}
			return 0;
		},
		is:{
			/**
			 * 判断传入的参数的属性是否相同(参数可以为卡牌、卡牌信息、属性等)
			 * @param ...infos 要判断的属性列表 
			 * @param every {boolean} 是否判断每一个传入的属性是否完全相同而不是存在部分相同
			 */
			sameNature:function(){
				let processedArguments=[],every=false;
				Array.from(arguments).forEach(argument=>{
					if(typeof argument=='boolean') every=argument;
					else if(argument) processedArguments.push(argument);
				});
				if(!processedArguments.length) return true;
				if(processedArguments.length==1){
					const argument=processedArguments[0];
					if(!Array.isArray(argument)) return false;
					if(!argument.length) return true;
					if(argument.length==1) return false;
					processedArguments=argument;
				}
				const naturesList=processedArguments.map(card=>{
					if(typeof card=='string') return card.split(lib.natureSeparator);
					else if(Array.isArray(card)) return card;
					return get.natureList(card||{});
				});
				const testingNaturesList=naturesList.slice(0,naturesList.length-1);
				if(every) return testingNaturesList.every((natures,index)=>naturesList.slice(index+1).every(testingNatures=>testingNatures.length==natures.length&&testingNatures.every(nature=>natures.includes(nature))));
				return testingNaturesList.every((natures,index)=>{
					const comparingNaturesList=naturesList.slice(index+1);
					return natures.some(nature=>comparingNaturesList.every(testingNatures=>testingNatures.includes(nature)));
				});
			},
			/**
			 * 判断传入的参数的属性是否不同(参数可以为卡牌、卡牌信息、属性等)
			 * @param ...infos 要判断的属性列表 
			 * @param every {boolean} 是否判断每一个传入的属性是否完全不同而不是存在部分不同
			 */
			differentNature:function(){
				let processedArguments=[],every=false;
				Array.from(arguments).forEach(argument=>{
					if(typeof argument=='boolean') every=argument;
					else if(argument) processedArguments.push(argument);
				});
				if(!processedArguments.length) return false;
				if(processedArguments.length==1){
					const argument=processedArguments[0];
					if(!Array.isArray(argument)) return true;
					if(!argument.length) return false;
					if(argument.length==1) return true;
					processedArguments=argument;
				}
				const naturesList=processedArguments.map(card=>{
					if(typeof card=='string') return card.split(lib.natureSeparator);
					else if(Array.isArray(card)) return card;
					return get.natureList(card||{});
				});
				const testingNaturesList=naturesList.slice(0,naturesList.length-1);
				if(every) return testingNaturesList.every((natures,index)=>naturesList.slice(index+1).every(testingNatures=>testingNatures.every(nature=>!natures.includes(nature))));
				return testingNaturesList.every((natures,index)=>{
					const comparingNaturesList=naturesList.slice(index+1);
					return natures.some(nature=>comparingNaturesList.every(testingNatures=>testingNatures.some(testingNature=>testingNature!=nature)));
				});
			},
			//判断一张牌是否为明置手牌
			shownCard:card=>{
				if(!card) return false;
				const gaintag=card.gaintag;
				return Array.isArray(gaintag)&&gaintag.some(tag=>tag.startsWith('visible_'));
			},
			//是否是虚拟牌
			vituralCard:card=>card.isCard||(!("cards" in card)||!Array.isArray(card.cards)||card.cards.length==0),
			//是否是转化牌
			convertedCard:card=>!card.isCard&&("cards" in card)&&Array.isArray(card.cards)&&card.cards.length>0,
			//是否是实体牌
			ordinaryCard:card=>card.isCard&&("cards" in card)&&Array.isArray(card.cards)&&card.cards.length==1,
			//押韵判断
			yayun:function(str1,str2){
				if(str1==str2) return true;
				var pinyin1=get.pinyin(str1,false),pinyin2=get.pinyin(str2,false);
				if(!pinyin1.length||!pinyin2.length) return false;
				var pron1=pinyin1[pinyin1.length-1],pron2=pinyin2[pinyin2.length-1];
				if(pron1==pron2) return true;
				return get.yunjiao(pron1)==get.yunjiao(pron2);
			},
			blocked:function(skill,player){
				if(!player.storage.skill_blocker||!player.storage.skill_blocker.length) return false;
				for(var i of player.storage.skill_blocker){
					if(lib.skill[i]&&lib.skill[i].skillBlocker&&lib.skill[i].skillBlocker(skill,player)) return true;
				}
				return false;
			},
			double:(name,array)=>{
				const extraInformations=get.character(name,4);
				if(!extraInformations) return false;
				for(const extraInformation of extraInformations){
					if(!extraInformation.startsWith('doublegroup:')) continue;
					return array?extraInformation.split(':').slice(1):true;
				}
				return false;
			},
			//Check if the card has a Yingbian condition
			//检测此牌是否具有应变条件
			yingbianConditional:card=>get.is.complexlyYingbianConditional(card)||get.is.simplyYingbianConditional(card),
			complexlyYingbianConditional:card=>{
				for(const key of lib.yingbian.condition.complex.keys()){
					if(get.cardtag(card,`yingbian_${key}`)) return true;
				}
				return false;
			},
			simplyYingbianConditional:card=>{
				for(const key of lib.yingbian.condition.simple.keys()){
					if(get.cardtag(card,`yingbian_${key}`)) return true;
				}
				return false;
			},
			//Check if the card has a Yingbian effect
			//检测此牌是否具有应变效果
			yingbianEffective:card=>{
				for(const key of lib.yingbian.effect.keys()){
					if(get.cardtag(card,`yingbian_${key}`)) return true;
				}
				return false;
			},
			yingbian:card=>get.is.yingbianConditional(card)||get.is.yingbianEffective(card),
			emoji:function(substring){
				if(substring){
					var reg=new RegExp("[~#^$@%&!?%*]",'g');
					if(substring.match(reg)){
						return true;
					}
					for(var i=0;i<substring.length;i++){
						var hs=substring.charCodeAt(i);
						if(0xd800<=hs&&hs<=0xdbff){
							if(substring.length>1){
								var ls=substring.charCodeAt(i+1);
								var uc=((hs-0xd800)*0x400)+(ls-0xdc00)+0x10000;
								if(0x1d000<=uc&&uc<=0x1f77f){
									return true;
								}
							}
						}
						else if(substring.length>1){
							var ls=substring.charCodeAt(i+1);
							if(ls==0x20e3){
								return true;
							}
						}
						else{
							if(0x2100<=hs&&hs<=0x27ff){
								return true;
							}
							else if(0x2B05<=hs&&hs<=0x2b07){
								return true;
							}
							else if(0x2934<=hs&&hs<=0x2935){
								return true;
							}
							else if(0x3297<=hs&&hs<=0x3299){
								return true;
							}
							else if(hs==0xa9||hs==0xae||hs==0x303d||hs==0x3030
								||hs==0x2b55||hs==0x2b1c||hs==0x2b1b
								||hs==0x2b50){
								return true;
							}
						}
					}
				}
				return false;
			},
			banWords:function(str){
				if(get.is.emoji(str)) return true;
				for(var i of window.bannedKeyWords){
					if(str.includes(i)) return true;
				}
				return false;
			},
			converted:function(event){
				return !(event.card&&event.card.isCard);
			},
			safari:function(){
				var ua=navigator.userAgent.toLowerCase();
				return ua.indexOf('safari'!=-1)&&ua.indexOf('chrome')==-1;
			},
			freePosition:function(cards){
				for(var i=0;i<cards.length;i++){
					if(!cards[i].hasPosition) return false;
					if(cards[i].hasPosition()) return false;
				}
				return true;
			},
			nomenu:function(name,item){
				var menus=['system','menu'];
				var configs={
					show_round_menu:lib.config.show_round_menu,
					round_menu_func:lib.config.round_menu_func,
					touchscreen:lib.config.touchscreen,
					swipe_up:lib.config.swipe_up,
					swipe_down:lib.config.swipe_down,
					swipe_left:lib.config.swipe_left,
					swipe_right:lib.config.swipe_right,
					right_click:lib.config.right_click,
					phonelayout:lib.config.phonelayout
				};
				configs[name]=item;
				if(!configs.phonelayout) return false;
				if(configs.show_round_menu&&menus.contains(configs.round_menu_func)){
					return false;
				}
				if(configs.touchscreen){
					if(menus.contains(configs.swipe_up)) return false;
					if(menus.contains(configs.swipe_down)) return false;
					if(menus.contains(configs.swipe_left)) return false;
					if(menus.contains(configs.swipe_right)) return false;
				}
				else{
					if(configs.right_click=='config') return false;
				}
				if(name){
					setTimeout(function(){
						alert('请将至少一个操作绑定为显示按钮或打开菜单,否则将永远无法打开菜单');
					});
				}
				return true;
			},
			altered:function(skill){
				return false;
				// if(_status.connectMode) return true;
				// return !lib.config.vintageSkills.contains(skill);
			},
			node:function(obj){
				var str=Object.prototype.toString.call(obj);
				if(str&&str.indexOf('[object HTML')) return true;
				return false;
			},
			div:function(obj){
				return Object.prototype.toString.call(obj) === '[object HTMLDivElement]';
			},
			map:function(obj){
				return Object.prototype.toString.call(obj) === '[object Map]';
			},
			set:function(obj){
				return Object.prototype.toString.call(obj) === '[object Set]';
			},
			object:function(obj){
				return Object.prototype.toString.call(obj) === '[object Object]';
			},
			singleSelect:function(func){
				if(typeof func=='function') return false;
				var select=get.select(func);
				return select[0]==1&&select[1]==1;
			},
			jun:function(name){
				if(get.mode()=='guozhan'){
					if(name&&typeof name=='object'){
						if(name.isUnseen&&name.isUnseen(0)) return false;
						name=name.name1;
					}
					if(typeof name=='string'&&name.startsWith('gz_jun_')){
						return true;
					}
				}
				return false;
			},
			versus:function(){
				return !_status.connectMode&&get.mode()=='versus'&&_status.mode=='three';
			},
			changban:function(){
				return get.mode()=='single'&&_status.mode=='changban';
			},
			single:function(){
				return get.mode()=='single'&&_status.mode=='normal';
			},
			mobileMe:function(player){
				return (game.layout=='mobile'||game.layout=='long')&&!game.chess&&player.dataset.position==0;
			},
			newLayout:function(){
				if(game.layout!='default') return true;
				return false;
			},
			phoneLayout:function(){
				if(!lib.config.phonelayout) return false;
				return (game.layout=='mobile'||game.layout=='long'||game.layout=='long2'||game.layout=='nova');
			},
			singleHandcard:function(){
				if(game.singleHandcard||game.layout=='mobile'||game.layout=='long'||game.layout=='long2'||game.layout=='nova'){
					return true;
				}
				return false;
			},
			linked2:function(player){
				if(game.chess) return true;
				if(lib.config.link_style2!='rotate') return true;
				// if(game.chess) return false;
				if(game.layout=='long'||game.layout=='long2'||game.layout=='nova') return true;
				if(player.dataset.position=='0'){
					return ui.arena.classList.contains('oblongcard');
				}
				return false;
			},
			empty:function(obj){
				for(var i in obj) return false;
				return true;
			},
			pos:function(str){
				return (str=='h'||str=='e'||str=='j'||str=='he'||str=='hj'||str=='ej'||str=='hej');
			},
			locked:function(skill,player){
				var info=lib.skill[skill];
				if(typeof info.locked=='function') return info.locked(skill,player);
				if(info.locked==false) return false;
				if(info.trigger&&info.forced) return true;
				if(info.mod) return true;
				if(info.locked) return true;
				return false;
			},
		},
		bottomCards:function(num,putBack){
			if(_status.waitingForCards){
				ui.create.cards.apply(ui.create,_status.waitingForCards);
				delete _status.waitingForCards;
			}
			var list=[];
			var card=false;
			if(typeof num!='number') num=1;
			if(num==0) {card=true;num=1;}
			if(num<0) num=1;
			while(num--){
				if(ui.cardPile.hasChildNodes()==false){
					game.washCard();
				}
				if(ui.cardPile.hasChildNodes()==false){
					game.over('平局');
					return [];
				}
				var cardx=ui.cardPile.removeChild(ui.cardPile.lastChild);
				cardx.original='c';
				list.push(cardx);
			}
			if(putBack){
				for(let i=list.length-1;i>=0;i--){
					ui.cardPile.appendChild(list[i]);
				}
			}
			game.updateRoundNumber();
			if(card) return list[0];
			return list;
		},
		discarded:function(){
			var list=_status.discarded.slice(0);
			for(var i=0;i<list.length;i++){
				if(list[i].parentNode!=ui.discardPile){
					list.splice(i--,1);
				}
			}
			return list;
		},
		cardOffset:function(){
			var x=ui.arena.getBoundingClientRect();
			var y=ui.window.getBoundingClientRect();
			return -y.width/2+(x.left+x.width/2);
		},
		colorspan:function(str){
			if(str[0]=='#'){
				var color;
				switch(str[1]){
					case 'r':color='fire';break;
					case 'p':color='legend';break;
					case 'b':color='blue';break;
					case 'g':color='green';break;
					default:return str.slice(2);
				}
				return '<span class="'+color+'text '+color+'auto">'+str.slice(2)+'</span>';
			}
			return str;
		},
		evtprompt:function(next,str){
			if(next.prompt){
				next.set('prompt2',str);
			}
			else{
				if(str.startsWith('###')){
					var prompts=str.slice(3).split('###');
					if(prompts[0]) next.set('prompt',prompts[0]);
					if(prompts[1]) next.set('prompt2',prompts[1]);
				}
				else{
					next.set('prompt',str);
				}
			}
		},
		autoViewAs:function(card,cards){
			let _card;
			if(get.itemtype(card)=='card'){
				_card={
					name:get.name(card),
					suit:get.suit(card),
					color:get.suit(card),
					number:get.number(card),
					nature:get.nature(card),
					isCard:true,
					cardid:card.cardid,
					wunature:card.wunature,
					storage:get.copy(card.storage),
				};
				if(Array.isArray(cards)) _card.cards=cards.slice(0);
				else _card.cards=[card];
			}
			else{
				_card=get.copy(card);
				if(Array.isArray(cards)){
					if(_card.cards){
						_card.cards=cards.slice(0);
					}
					else{
						_card.cards=cards.slice(0);
						if(!lib.suits.includes(_card.suit)) _card.suit=get.suit(_card);
						if(!Object.keys(lib.color).includes(_card.color)) _card.color=get.color(_card);
						if(!_card.hasOwnProperty('number')) _card.number=get.number(_card);
						if(!_card.hasOwnProperty('nature')) _card.nature=(get.nature(_card)||false);
					}
				}
			}
			const info=get.info(_card,false);
			if(info.autoViewAs){
				_card.name=info.autoViewAs;
			}
			return _card;
		},
		//deprecated
		_autoViewAs:function(card,cards){
			var info=get.info(card);
			if(info.autoViewAs){
				if(cards===false){
					return {
						name:info.autoViewAs,
					};
				}
				else if(Array.isArray(cards)){
					return {
						name:info.autoViewAs,
						cards:cards.slice(0),
					};
				}
				else if(get.itemtype(card)=='card'){
					return {
						name:info.autoViewAs,
						cards:[card],
					};
				}
				else{
					return {
						name:info.autoViewAs,
						suit:card.suit,
						number:card.number,
						nature:card.nature,
					};
				}
			}
			else{
				if(card.isCard||get.itemtype(card)=='card'){
					var next={
						name:get.name(card),
						suit:get.suit(card),
						number:get.number(card),
						nature:get.nature(card),
						isCard:true,
						cardid:card.cardid,
						wunature:card.wunature,
						storage:get.copy(card.storage),
						cards:get.copy(card.cards),
					};
					if(get.itemtype(cards)=='cards'&&!card.cards) next.cards=cards.slice(0);
					else if(get.itemtype(card)=='card') next.cards=[card];
					return next;
				}
				else if(get.is.object(card)&&get.itemtype(cards)=='cards'&&!card.cards){
					card=get.copy(card);
					card.cards=cards.slice(0);
				}
				return card;
			}
		},
		max:function(list,func,type){
			list=list.slice(0);
			if(typeof func=='string'){
				var key=func;
				func=function(item){
					return item[key];
				}
			}
			list.sort(function(a,b){
				return func(b)-func(a);
			});
			if(type=='list'){
				var list2=[];
				for(var i=0;i<list.length;i++){
					if(func(list[i])==func(list[0])){
						list2.push(list[i]);
					}
				}
				return list2;
			}
			else if(type=='item'){
				return list[0];
			}
			else{
				return func(list[0]);
			}
		},
		min:function(list,func,type){
			list=list.slice(0);
			if(typeof func=='string'){
				var key=func;
				func=function(item){
					return item[key];
				}
			}
			list.sort(function(a,b){
				return func(a)-func(b);
			});
			if(type=='list'){
				var list2=[];
				for(var i=0;i<list.length;i++){
					if(func(list[i])==func(list[0])){
						list2.push(list[i]);
					}
				}
				return list2;
			}
			else if(type=='item'){
				return list[0];
			}
			else{
				return func(list[0]);
			}
		},
		character:function(name,num){
			let info=lib.character[name];
			if(!info){
				const pack=Object.keys(lib.characterPack).find(pack=>lib.characterPack[pack].hasOwnProperty(name));
				if(pack) info=lib.characterPack[pack][name];
			}
			if(info){
				if(typeof num=='number'){
					return info[num];
				}
				return info;
			}
			return null;
		},
		characterIntro:function(name){
			if(lib.characterIntro[name]) return lib.characterIntro[name];
			var tags=get.character(name,4);
			if(tags){
				for(var i=0;i<tags.length;i++){
					if(tags[i].startsWith('des:')){
						return tags[i].slice(4);
					}
				}
			}
			while(name.includes('_')&&!lib.characterIntro[name]){
				name=name.slice(name.indexOf('_')+1);
			}
			if(lib.characterIntro[name]) return lib.characterIntro[name];
			return '暂无武将介绍';
		},
		bordergroup:(info,raw)=>{
			if(!Array.isArray(info)){
				info=lib.character[info];
				if(!info) return '';
			}
			if(Array.isArray(info[4])) for(const str of info[4]){
				if(typeof str=='string'&&str.startsWith('border:')) return str.slice(7);
			}
			return raw?'':info[1]||'';
		},
		groupnature:function(group,method){
			var nature=lib.groupnature[group];
			if(!nature) return '';
			if(method=='raw'){
				return nature;
			}
			return nature+'mm';
		},
		sgn:function(num){
			if(num>0) return 1;
			if(num<0) return -1;
			return 0;
		},
		rand:function(num,num2){
			if(typeof num2=='number'){
				return num+Math.floor(Math.random()*(num2-num+1));
			}
			else{
				return Math.floor(Math.random()*num);
			}
		},
		sort:function(arr,method){
			switch(method){
				case 'seat':{
					lib.tempSortSeat=arguments[2];
					arr.sort(lib.sort.seat);
					delete lib.tempSortSeat;
					return arr;
				}
			}
		},
		sortSeat:function(arr,target){
			lib.tempSortSeat=target;
			arr.sort(lib.sort.seat);
			delete lib.tempSortSeat;
			return arr;
		},
		zip:function(callback){
			if(!window.JSZip){
				lib.init.js(lib.assetURL+'game','jszip',function(){
					callback(new JSZip());
				});
			}
			else{
				callback(new JSZip());
			}
		},
		delayx:function(num,max){
			if(typeof num!='number') num=1;
			if(typeof max!='number') max=Infinity;
			switch(lib.config.game_speed){
				case 'vslow':return Math.min(max,2.5*num);
				case 'slow':return Math.min(max,1.5*num);
				case 'fast':return Math.min(max,0.7*num);
				case 'vfast':return Math.min(max,0.4*num);
				case 'vvfast':return Math.min(max,0.2*num);
				default:return Math.min(max,num);
			}
		},
		prompt:function(skill,target,player){
			player=player||_status.event.player;
			if(target){
				var str=get.translation(target);
				if(target==player){
					str+='(你)'
				}
				return '是否对'+str+'发动【'+get.skillTranslation(skill,player)+'】?';
			}
			else{
				return '是否发动【'+get.skillTranslation(skill,player)+'】?';
			}
		},
		prompt2:function(skill,target,player){
			var str=get.prompt.apply(this,arguments);
			if(!lib.translate[skill+'_info']) return str;
			return '###'+str+'###'+lib.translate[skill+'_info'];
		},
		url:function(master){
			var url=lib.config.updateURL||lib.updateURL;
			if(url[url.length-1]!='/'){
				url+='/';
			}
			if(master!='nodev'){
				return url+'master/';
			}
			else{
				return url+'v'+lib.version+'/';
			}
		},
		round:function(num,f){
			var round=1;
			for(var i=0;i<f;i++){
				round*=10;
			}
			return Math.round(num*round)/round;
		},
		playerNumber:function(){
			var num;
			if(_status.brawl&&_status.brawl.playerNumber){
				num=_status.brawl.playerNumber
			}
			else{
				num=get.config('player_number');
			}
			return parseInt(num)||2;
		},
		benchmark:function(func1,func2,iteration,arg){
			var tic,toc;
			var key1,key2;
			if(!arg) arg=[];
			if(Array.isArray(func2)){
				key1=func2[0];
				key2=func2[1];
			}
			else if(typeof func2=='string'){
				key1=func2;
				func2=iteration||100;
			}
			else if(typeof func2=='number'){
				arg=iteration||arg;
				iteration=func2;
			}
			tic=get.utc();
			for(var i=0;i<iteration;i++){
				if(key1){
					func1[key1](arg.randomGet());
				}
				else{
					func1(arg.randomGet());
				}
			}
			toc=get.utc();
			if(typeof func2=='number'){
				return toc-tic;
			}
			console.log('time1: '+(toc-tic));
			tic=get.utc();
			for(var i=0;i<iteration;i++){
				if(key2){
					func1[key2](arg.randomGet());
				}
				else{
					func2(arg.randomGet());
				}
			}
			toc=get.utc();
			console.log('time2: '+(toc-tic));
		},
		stringify:function(obj,level){
			level=level||0;
			var indent='';
			var str;
			for(var i=0;i<level;i++){
				indent+='    ';
			}
			if(get.objtype(obj)=='object'){
				str='{\n';
				for(var i in obj){
					if(/[^a-zA-Z]/.test(i)){
						str+=indent+'    "'+i+'":'+get.stringify(obj[i],level+1)+',\n';
					}
					else{
						str+=indent+'    '+i+':'+get.stringify(obj[i],level+1)+',\n';
					}
				}
				str+=indent+'}';
				return str;
			}
			else{
				if(typeof obj=='function'){
					str=obj.toString();
					str=str.replace(/\t/g,'    ');
					var i=str.lastIndexOf('\n');
					var num=0;
					for(var j=i+1;j<str.length&&str[j]==' ';j++){
						num++;
					}
					num=Math.floor(num/4);
					for(i=0;i<num-level;i++){
						str=str.replace(/\n    /g,'\n');
					}
				}
				else{
					try{
						if(Array.isArray(obj)&&obj.contains(Infinity)){
							obj=obj.slice(0);
							var rand=get.id();
							for(var i=0;i<obj.length;i++){
								if(obj[i]===Infinity){
									obj[i]=parseInt(rand);
								}
							}
							str=JSON.stringify(obj).replace(new RegExp(rand,'g'),'Infinity');
						}
						else{
							str=JSON.stringify(obj)||'';
						}
					}
					catch(e){
						str='';
					}
				}
				return str;
			}
		},
		copy:function(obj){
			if(get.objtype(obj)=='object'){
				var copy={};
				for(var i in obj){
					copy[i]=get.copy(obj[i]);
				}
				return copy;
			}
			else if(Array.isArray(obj)){
				var copy=[];
				for(var i=0;i<obj.length;i++){
					copy.push(get.copy(obj[i]));
				}
				return copy;
			}
			else{
				return obj;
			}
		},
		inpilefull:function(type){
			var list=[];
			for(var i in lib.cardPile){
				for(var j=0;j<lib.cardPile[i].length;j++){
					var info=lib.cardPile[i][j];
					if(lib.inpile.contains(info[2])&&get.type(info[2])==type){
						list.push({
							name:info[2],
							suit:info[0],
							number:info[1],
							nature:info[3]
						});
					}
				}
			}
			return list;
		},
		inpile:function(type,filter){
			var list=[];
			if(filter=='trick'){
				for(var i=0;i<lib.inpile.length;i++){
					if(get.type(lib.inpile[i],'trick')==type) list.push(lib.inpile[i]);
				}
			}
			else{
				for(var i=0;i<lib.inpile.length;i++){
					if(typeof type=='function'){
						if(type(lib.inpile[i])){
							list.push(lib.inpile[i]);
						}
					}
					else{
						if(typeof filter=='function'&&!filter(lib.inpile[i])) continue;
						if(type.startsWith('equip')&&type.length==6){
							if(get.subtype(lib.inpile[i])==type) list.push(lib.inpile[i]);
						}
						else{
							if(get.type(lib.inpile[i])==type) list.push(lib.inpile[i]);
						}
					}
				}
			}
			return list;
		},
		inpile2:function(type){
			return get.inpile(type,'trick');
		},
		typeCard:function(type,filter){
			var list=[];
			for(var i in lib.card){
				if(lib.card[i].mode&&lib.card[i].mode.contains(get.mode())==false) continue;
				// if(lib.card[i].vanish||lib.card[i].destroy) continue;
				if(lib.card[i].destroy) continue;
				if(typeof filter=='function'&&!filter(i)) continue;
				if(lib.config.bannedcards.contains(i)) continue;
				if(!lib.translate[i+'_info']) continue;
				if((type.startsWith('equip')&&type.length==6)||
					(type.startsWith('hslingjian')&&type.length==11)||
					(type.startsWith('spell_'))){
					if(get.subtype(i)==type) list.push(i);
				}
				else{
					if(get.type(i)==type) list.push(i);
				}
			}
			return list;
		},
		libCard:function(filter){
			var list=[];
			for(var i in lib.card){
				if(lib.card[i].mode&&lib.card[i].mode.contains(get.mode())==false) continue;
				// if(lib.card[i].vanish||lib.card[i].destroy) continue;
				if(lib.card[i].destroy) continue;
				if(lib.config.bannedcards.contains(i)) continue;
				if(!lib.translate[i+'_info']) continue;
				if(filter(lib.card[i],i)){
					list.push(i);
				}
			}
			return list;
		},
		ip:function(){
			if(!require) return '';
			var interfaces = require('os').networkInterfaces();
			for(var devName in interfaces){
				var iface = interfaces[devName];
				for(var i=0;i<iface.length;i++){
					var alias = iface[i];
					if(alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){
						return alias.address;
					}
				}
			}
		},
		modetrans:function(config,server){
			if(config.mode=='doudizhu'){
				switch(config.doudizhu_mode){
					case 'kaihei':return '开黑斗地主';
					case 'huanle':return '欢乐斗地主';
					case 'binglin':return '兵临城下';
					case 'online':return '智斗三国';
					default:return '休闲'+(config.double_character?'双将':'')+'斗地主';
				}
			}
			if(config.mode=='versus'){
				switch(config.versus_mode){
					case '1v1':return '单人对决';
					case '2v2':return '欢乐成双';
					case '3v3':return '血战到底';
					case '4v4':return '四人对决';
					case 'guandu':return '官渡之战';
				}
			}
			else if(config.mode=='single'){
				switch(config.single_mode){
					case 'normal':return '新1v1';
					case 'changban':return '血战长坂坡';
					case 'dianjiang':return '点将单挑';
				}
			}
			else if(config.mode=='identity'){
				switch(config.identity_mode){
					case 'purple':return '三对三对二';
					case 'zhong':return (config.double_character?'双将':'')+'忠胆英杰';
					default:return get.cnNumber(parseInt(config.number))+'人'+(config.double_character?'双将':'')+'身份';
				}
			}
			else if(config.mode=='guozhan'&&config.guozhan_mode!='normal'){
				switch(config.guozhan_mode){
					case 'yingbian':return '应变国战';
					case 'old':return '怀旧国战';
				}
			}
			else{
				if(server){
					return get.translation(config.mode)+'模式';
				}
				else{
					return get.cnNumber(parseInt(config.number))+'人'+get.translation(config.mode);
				}
			}
		},
		charactersOL:function(func){
			var list=[];
			var libCharacter={};
			for(var i=0;i<lib.configOL.characterPack.length;i++){
				var pack=lib.characterPack[lib.configOL.characterPack[i]];
				for(var j in pack){
					if(typeof func=='function'&&func(j)) continue;
					if(lib.connectBanned.contains(j)) continue;
					if(lib.character[j]) libCharacter[j]=pack[j];
				}
			}
			for(i in libCharacter){
				if(lib.filter.characterDisabled(i,libCharacter)) continue;
				list.push(i);
			}
			return list;
		},
		trimip:function(str){
			var len=str.length-5;
			if(str.lastIndexOf(':8080')==len){
				str=str.slice(0,len);
			}
			return str;
		},
		mode:()=>lib[_status.connectMode?'configOL':'config'].mode,
		idDialog:function(id){
			for(var i=0;i<ui.dialogs.length;i++){
				if(ui.dialogs[i].videoId==id){
					return ui.dialogs[i];
				}
			}
			return null;
		},
		arenaState:function(){
			var state={
				number:ui.arena.dataset.number,
				players:{},
				mode:_status.mode,
				dying:_status.dying,
				servermode:window.isNonameServer,
				roomId:game.roomId,
				over:_status.over,
				inpile:lib.inpile,
				inpile_nature:lib.inpile_nature,
				renku:_status.renku,
			};
			for(var i in lib.playerOL){
				state.players[i]=lib.playerOL[i].getState();
			}
			return state;
		},
		skillState:function(player){
			var skills={
				global:lib.skill.global
			};
			var skillinfo={};
			for(var i in lib.playerOL){
				skills[i]={
					skills:lib.playerOL[i].skills,
					hiddenSkills:lib.playerOL[i].hiddenSkills,
					invisibleSkills:lib.playerOL[i].invisibleSkills,
					additionalSkills:lib.playerOL[i].additionalSkills,
					disabledSkills:lib.playerOL[i].disabledSkills,
					tempSkills:lib.playerOL[i].tempSkills,
					storage:lib.playerOL[i].storage,
				}
			}
			//for(var i in lib.skill){
			//	if(lib.skill[i].chooseButton&&lib.skill[i].enable){
			//		skillinfo[i]=lib.skill[i].chooseButton;
			//	}
			//}
			skills.skillinfo=skillinfo;
			if(player){
				skills.stat=player.getStat();
			}
			return skills;
		},
		id:function(){
			return (Math.floor(1000000+9000000*Math.random())).toString()+(10+lib.status.globalId++);
		},
		zhu:function(player,skill,group){
			if(typeof player=='string'){
				skill=player;
				player=null;
			}
			var mode=get.mode();
			if(mode=='identity'){
				if(_status.mode=='purple'){
					if(!player) return null;
					var zhu=game[player.identity.slice(0,1)+'Zhu'];
					if(!zhu) return null;
					if(skill&&!zhu.hasSkill(skill)) return null;
					return zhu;
				}
				if(!game.zhu) return null;
				if(skill&&!game.zhu.hasSkill(skill)) return null;
				if(game.zhu.isZhu) return game.zhu;
			}
			else if(mode=='versus'&&(_status.mode=='four'||_status.mode=='guandu')){
				for(var i=0;i<game.players.length;i++){
					if(game.players[i].isZhu){
						if(skill&&!(game.players[i].hasSkill(skill))) continue;
						if(!player) return game.players[i];
						if(player.side==game.players[i].side){
							return game.players[i];
						}
					}
				}
			}
			else if(mode=='guozhan'){
				for(var i=0;i<game.players.length;i++){
					if(get.is.jun(game.players[i])&&!game.players[i].isUnseen()){
						if(skill&&!game.players[i].hasSkill(skill)) continue;
						if(!player) return game.players[i];
						if(player.identity==game.players[i].identity){
							return game.players[i];
						}
						else if(group&&group==game.players[i].identity){
							return game.players[i];
						}
					}
				}
			}
			return null;
		},
		config:function(item,mode){
			mode=mode||lib.config.mode;
			if(!lib.config.mode_config[mode]) return;
			return lib.config.mode_config[mode][item];
		},
		coinCoeff:function(list){
			var num=0;
			for(var i=0;i<list.length;i++){
				var rank=get.rank(list[i]);
				switch(rank){
					case 'sp':return 0.1;
					case 's':num+=0.4;break;
					case 'ap':num+=0.6;break;
					case 'a':num+=0.8;break;
					case 'am':num+=0.95;break;
					case 'bp':num+=1.05;break;
					case 'b':num+=1.2;break;
					case 'bm':num+=1.4;break;
					case 'c':num+=1.6;break;
					case 'd':num+=1.8;break;
				}
			}
			return num/list.length;
		},
		rank:function(name,num){
			if(typeof name=='object'&&name.name){
				name=name.name;
			}
			if(num==true) num=9;
			if(typeof num!='number') num=false;
			if(name==_status.lord) return num?Math.round(7*(num-1)/8+1):'ap';
			var rank=lib.rank;
			if(lib.characterPack.standard[name]||lib.characterPack.shenhua[name]){
				var skills;
				if(lib.character[name]){
					skills=lib.character[name][3];
				}
				else{
					var tmpinfo=get.character(name);
					if(tmpinfo){
						skills=tmpinfo[3];
					}
					else{
						skills=[];
					}
				}
				for(var i=0;i<skills.length;i++){
					if(skills[i].alter&&!lib.config.vintageSkills.contains(skills[i])){
						name=lib.rank.a[0];break;
					}
				}
			}
			if(rank.s.contains(name)) return num?Math.round(8*(num-1)/8+1):'s';
			if(rank.ap.contains(name)) return num?Math.round(7*(num-1)/8+1):'ap';
			if(rank.a.contains(name)) return num?Math.round(6*(num-1)/8+1):'a';
			if(rank.am.contains(name)) return num?Math.round(5*(num-1)/8+1):'am';
			if(rank.bp.contains(name)) return num?Math.round(4*(num-1)/8+1):'bp';
			if(rank.b.contains(name)) return num?Math.round(3*(num-1)/8+1):'b';
			if(rank.bm.contains(name)) return num?Math.round(2*(num-1)/8+1):'bm';
			if(rank.c.contains(name)) return num?Math.round(1*(num-1)/8+1):'c';
			if(rank.d.contains(name)) return num?Math.round(0*(num-1)/8+1):'d';
			if(lib.character[name]&&lib.character[name][4]){
				if(lib.character[name][4].contains('boss')||
				lib.character[name][4].contains('bossallowed')||
				lib.character[name][4].contains('hiddenboss')){
					return num?Math.round(9*(num-1)/8+1):'sp';
				}
			}
			return num?Math.round(9*(num-1)/8+1):'x';
		},
		skillRank:function(skill,type,grouped){
			var info=lib.skill[skill];
			var player=_status.event.skillRankPlayer||_status.event.player;
			if(!info) return 0;
			if(info.ai){
				if(info.ai.halfneg) return 0;
				if(typeof info.ai.combo=='string'&&player&&!player.hasSkill(info.ai.combo)){
					return 0;
				}
				if(info.ai.neg) return -1;
			}
			var num=1;
			var threaten=1;
			if(info.ai&&info.ai.threaten){
				if(typeof info.ai.threaten=='number'){
					threaten=info.ai.threaten;
				}
				else if(typeof info.ai.threaten=='function'&&player){
					threaten=info.ai.threaten(player,player);
				}
			}
			if(type&&type.includes('in')){
				if(info.enable=='phaseUse') num+=0.5;
				if(info.trigger&&info.trigger.player){
					var list=Array.isArray(info.trigger.player)?info.trigger.player:[info.trigger.player];
					var add=false;
					for(var i of list){
						if(i.startsWith('phase')){
							num+=0.5;
							add=true;
						}
						else{
							for(var j of lib.phaseName){
								if(i.indexOf[j]==0){
									num+=0.5;
									add=true;
									break;
								}
							}
						}
						if(add) break;
					}
				}
				if(info.trigger&&((typeof info.trigger.player=='string'&&info.trigger.player.startsWith('use'))||info.trigger.source)){
					num+=0.3;
				}
				if(num>1&&threaten>1){
					num+=Math.sqrt(threaten)-1;
				}
			}
			if(type&&type.includes('out')){
				if(threaten<1){
					num*=1/Math.sqrt(threaten);
				}
				if(info.trigger){
					if(info.trigger.global){
						var list=Array.isArray(info.trigger.global)?info.trigger.global:[info.trigger.global];
						num+=Math.min(3,list.length)/10;
						for(var i of list){
							if(i.startsWith('lose')||i.startsWith('use')) num+=0.3;
							if(i.startsWith('cardsDiscard')) num+=0.4;
						}
					}
					if(info.trigger.target||(typeof info.trigger.player=='string'&&
					(info.trigger.player.startsWith('damage')||info.trigger.player.startsWith('lose')))) num+=0.1;
				}
				if(info.ai){
					if(info.ai.maixie||info.ai.maixie_hp||info.ai.maixie_defend){
						num+=0.5;
					}
					if(info.ai.nolose||info.ai.noh||info.ai.noe||info.ai.nodiscard){
						num+=0.3;
					}
				}
			}
			if(!grouped){
				var groups=game.expandSkills([skill]);
				groups.remove(skill);
				var ggt=[];
				for(var i=0;i<groups.length;i++){
					var gi=get.skillRank(groups[i],type,true);
					if(gi<0){
						num-=0.5;
					}
					else if(gi>1){
						ggt.push(gi);
					}
				}
				if(ggt.length){
					num+=Math.max.apply(this,ggt)-1+ggt.length/20;
				}
			}
			return num;
		},
		targetsInfo:function(targets){
			var info=[];
			for(var i=0;i<targets.length;i++){
				info.push(targets[i].dataset.position);
			}
			return info;
		},
		infoTargets:function(info){
			var targets=[];
			for(var i=0;i<info.length;i++){
				targets.push(game.playerMap[info[i]]);
			}
			return targets;
		},
		cardInfo:function(card){
			return [card.suit,card.number,card.name,card.nature];
		},
		cardsInfo:function(cards){
			var info=[];
			for(var i=0;i<cards.length;i++){
				info.push(get.cardInfo(cards[i]));
			}
			return info;
		},
		infoCard:function(info){
			var card=ui.create.card();
			if(info[0]){
				card.init(info);
			}
			return card;
		},
		infoCards:function(info){
			var cards=[];
			for(var i=0;i<info.length;i++){
				cards.push(get.infoCard(info[i]));
			}
			return cards;
		},
		cardInfoOL:function(card){
			return '_noname_card:'+JSON.stringify([card.cardid,card.suit,card.number,card.name,card.nature]);
		},
		infoCardOL:function(info){
			if(!lib.cardOL) return info;
			var card;
			try{
				var info=JSON.parse(info.slice(13));
				var id=info.shift();
				if(!id){
					card=ui.create.card();
					if(info&&info[2]) card.init(info);
				}
				else if(lib.cardOL[id]){
					if(lib.cardOL[id].name!=info[2]){
						if(info&&info[2]) lib.cardOL[id].init(info);
					}
					card=lib.cardOL[id];
				}
				else if(game.online){
					card=ui.create.card();
					card.cardid=id;
					if(info&&info[2]) card.init(info);
					lib.cardOL[id]=card;
				}
			}
			catch(e){
				console.log(e);
			}
			return card||info;
		},
		cardsInfoOL:function(cards){
			var info=[];
			for(var i=0;i<cards.length;i++){
				info.push(get.cardInfoOL(cards[i]));
			}
			return info;
		},
		infoCardsOL:function(info){
			var cards=[];
			for(var i=0;i<info.length;i++){
				cards.push(get.infoCardOL(info[i]));
			}
			return cards;
		},
		playerInfoOL:function(player){
			return '_noname_player:'+player.playerid;
		},
		infoPlayerOL:function(info){
			if(!lib.playerOL) return info
			return lib.playerOL[info.slice(15)]||info;
		},
		playersInfoOL:function(players){
			var info=[];
			for(var i=0;i<players.length;i++){
				info.push(get.playerInfoOL(players[i]));
			}
			return info;
		},
		infoPlayersOL:function(info){
			var players=[];
			for(var i=0;i<info.length;i++){
				players.push(get.infoPlayerOL(info[i]));
			}
			return players;
		},
		funcInfoOL:function(func){
			if(typeof func=='function'){
				if(func._filter_args){
					return '_noname_func:'+JSON.stringify(get.stringifiedResult(func._filter_args,3));
				}
				return '_noname_func:'+func.toString();
			}
			return '';
		},
		infoFuncOL:function(info){
			var func;
			try{
				eval('func=('+info.slice(13)+');');
			}
			catch(e){
				return function(){};
			}
			if(Array.isArray(func)){
				func=get.filter.apply(this,get.parsedResult(func));
			}
			return func;
		},
		eventInfoOL:function(item,level,nomore){
			if(Object.prototype.toString.call(item)=='[object Object]'){
				var item2={};
				for(var i in item){
					if(i=='_trigger'){
						if(nomore===false) continue;
						else item2[i]=get.eventInfoOL(item[i],null,false);
					}
					else if(lib.element.event[i]||i=='content'||get.itemtype(item[i])=='event') continue;
					else item2[i]=get.stringifiedResult(item[i],null,false);
				}
				return '_noname_event:'+JSON.stringify(item2);
			}
			else{
				return '';
			}
		},
		infoEventOL:function(item){
			var evt;
			try{
				evt=JSON.parse(item.slice(14));
				for(var i in evt){
					evt[i]=get.parsedResult(evt[i]);
				}
				for(var i in lib.element.event) evt[i]=lib.element.event[i];
			}
			catch(e){
				console.log(e);
			}
			return evt||item;
		},
		stringifiedResult:function(item,level,nomore){
			if(!item) return item;
			if(typeof item=='function'){
				return get.funcInfoOL(item);
			}
			else if(typeof item=='object'){
				switch(get.itemtype(item)){
					case 'card': return get.cardInfoOL(item);
					case 'cards': return get.cardsInfoOL(item);
					case 'player': return get.playerInfoOL(item);
					case 'players': return get.playersInfoOL(item);
					case 'event': 
						if(nomore===false) return '';
						return get.eventInfoOL(item);
					default:
					if(typeof level!='number'){
						level=8;
					}
					if(Array.isArray(item)){
						if(level==0){
							return [];
						}
						var item2=[];
						for(var i=0;i<item.length;i++){
							item2.push(get.stringifiedResult(item[i],level-1,nomore));
						}
						return item2;
					}
					else if(Object.prototype.toString.call(item)=='[object Object]'){
						if(level==0){
							return {};
						}
						var item2={};
						for(var i in item){
							item2[i]=get.stringifiedResult(item[i],level-1,nomore);
						}
						return item2;
					}
					else{
						return {};
					}
				}
			}
			else if(item===Infinity){
				return '_noname_infinity';
			}
			else{
				return item;
			}
		},
		parsedResult:function(item){
			if(!item) return item;
			if(typeof item=='string'){
				if(item.startsWith('_noname_func:')){
					return get.infoFuncOL(item);
				}
				else if(item.startsWith('_noname_card:')){
					return get.infoCardOL(item);
				}
				else if(item.startsWith('_noname_player:')){
					return get.infoPlayerOL(item);
				}
				else if(item.startsWith('_noname_event:')){
					return get.infoEventOL(item);
				}
				else if(item=='_noname_infinity'){
					return Infinity;
				}
				else{
					return item;
				}
			}
			else if(Array.isArray(item)){
				var item2=[];
				for(var i=0;i<item.length;i++){
					item2.push(get.parsedResult(item[i]));
				}
				return item2;
			}
			else if(typeof item=='object'){
				var item2={};
				for(var i in item){
					item2[i]=get.parsedResult(item[i]);
				}
				return item2;
			}
			else{
				return item;
			}
		},
		verticalStr:function(str,sp){
			if(typeof str!='string') return '';
			return Array.from(str).filter(value=>value!='`').join('');
		},
		numStr:function(num,method){
			if(num==Infinity){
				if(method=='card') return get.selectableCards().length+ui.selected.cards.length;
				if(method=='target') return get.selectableTargets().length+ui.selected.targets.length;
				return '∞';
			}
			return num.toString();
		},
		rawName:function(str){
			let str2=lib.translate[str];
			if(lib.translate[str+'_ab']) str2=lib.translate[str+'_ab'];
			if(!str2) return '';
			if(lib.translate[str+'_prefix']&&str2.startsWith(lib.translate[str+'_prefix'])){
				return str2.slice(lib.translate[str+'_prefix'].length);
			}
			return str2;
		},
		//作用修改:只读前缀 不读_ab
		rawName2:function(str){
			let str2=lib.translate[str];
			if(!str2) return '';
			if(lib.translate[str+'_prefix']&&str2.startsWith(lib.translate[str+'_prefix'])){
				return str2.slice(lib.translate[str+'_prefix'].length);
			}
			return str2;
		},
		slimNameHorizontal:str=>{
			const slimName=lib.translate[`${str}_ab`]||lib.translate[str];
			if(!slimName) return '';
			const prefix=lib.translate[`${str}_prefix`];
			if(prefix&&slimName.startsWith(prefix)){
				//兼容版特化处理
				if(lib.compatibleEdition) return `${get.prefixSpan(prefix,str)}<span>${slimName.slice(prefix.length)} </span>`;
				return `${get.prefixSpan(prefix,str)}<span>${slimName.slice(prefix.length)}</span>`;
			}
			return slimName;
		},
		/**
		 * @param {string} prefix
		 * @param {string} name
		 * @returns {string}
		 */
		prefixSpan:(prefix,name)=>{
			let color='#ffffff',nature=false;
			const map=lib.namePrefix.get(prefix),config=lib.config.buttoncharacter_prefix;
			if(config=='off') return '';
			if(map){
				if(map.getSpan) return map.getSpan(prefix,name);
				if(map.color) color=map.color;
				if(map.nature) nature=map.nature;
				if(map.showName) prefix=map.showName;
			}
			if(config=='simple') return `<span>${prefix}</span>`
			return `<span style="color: ${color};"${nature?(`data-nature="${nature}"`):''}>${prefix}</span>`
		},
		slimName:function(str){
			return get.verticalStr(get.slimNameHorizontal(str),true);
		},
		time:function(){
			if(lib.status.dateDelaying){
				return lib.getUTC(lib.status.dateDelaying)-lib.getUTC(lib.status.date)-lib.status.dateDelayed;
			}
			else{
				return lib.getUTC(new Date())-lib.getUTC(lib.status.date)-lib.status.dateDelayed;
			}
		},
		utc:function(){
			return (new Date()).getTime();
		},
		evtDistance:function(e1,e2){
			var dx=(e1.clientX-e2.clientX)/game.documentZoom;
			var dy=(e1.clientY-e2.clientY)/game.documentZoom;
			return Math.sqrt(dx*dx+dy*dy);
		},
		xyDistance:function(from,to){
			return Math.sqrt((from[0]-to[0])*(from[0]-to[0])+(from[1]-to[1])*(from[1]-to[1]));
		},
		itemtype:function(obj){
			var i,j;
			if(typeof obj=='string'){
				if(obj.length<=5){
					var bool=true;
					for(i=0;i<obj.length;i++){
						if(/h|e|j|s|x/.test(obj[i])==false){
							bool=false;break;
						}
					}
					if(bool) return 'position';
				}
				if(obj.includes(lib.natureSeparator)&&obj.split(lib.natureSeparator).every(n=>lib.nature.has(n))) return 'natures';
				if(lib.nature.has(obj)) return 'nature';
			}
			if(Array.isArray(obj)&&obj.length){
				var isPlayers=true;
				for(i=0;i<obj.length;i++){
					if(get.itemtype(obj[i])!='player') {isPlayers=false;break;}
				}
				if(isPlayers) return 'players';

				var isCards=true;
				for(i=0;i<obj.length;i++){
					if(get.itemtype(obj[i])!='card') {isCards=false;break;}
				}
				if(isCards) return 'cards';

				if(obj.length==2){
					if(typeof obj[0]=='number'&&typeof obj[1]=='number'){
						if(obj[0]<=obj[1]||obj[1]<=-1) return 'select';
					}
				}

				if(obj.length==4){
					var isPosition=true;
					for(i=0;i<obj.length;i++){
						if(typeof obj[i]!='number') {isPosition=false;break;}
					}
					if(isPosition) return 'divposition';
				}
			}
			if(get.objtype(obj)=='div'){
				if(obj.classList.contains('button')) return 'button';
				if(obj.classList.contains('card')) return 'card';
				if(obj.classList.contains('player')) return 'player';
				if(obj.classList.contains('dialog')) return 'dialog';
			}
			if(get.is.object(obj)){
				if(obj.isMine==lib.element.event.isMine) return 'event';
			}
		},
		equipNum:function(card){
			if(get.type(card)=='equip'){
				return parseInt(get.subtype(card)[5]);
			}
			return 0;
		},
		objtype:function(obj){
			if(Object.prototype.toString.call(obj) === '[object Array]') return 'array';
			if(Object.prototype.toString.call(obj) === '[object Object]') return 'object';
			if(Object.prototype.toString.call(obj) === '[object HTMLDivElement]') return 'div';
			if(Object.prototype.toString.call(obj) === '[object HTMLTableElement]') return 'table';
			if(Object.prototype.toString.call(obj) === '[object HTMLTableRowElement]') return 'tr';
			if(Object.prototype.toString.call(obj) === '[object HTMLTableCellElement]') return 'td';
			if(Object.prototype.toString.call(obj) === '[object HTMLBodyElement]') return 'td';
		},
		type:function(obj,method,player){
			if(typeof obj=='string') obj={name:obj};
			if(typeof obj!='object') return;
			var name=get.name(obj,player);
			if(!lib.card[name]) return;
			if(method=='trick'&&lib.card[name].type=='delay') return 'trick';
			return lib.card[name].type;
		},
		type2:function(card,player){
			return get.type(card,'trick',player);
		},
		subtype:function(obj,player){
			if(typeof obj=='string') obj={name:obj};
			if(typeof obj!='object') return;
			var name=get.name(obj,player);
			if(!lib.card[name]) return;
			return lib.card[name].subtype;
		},
		equiptype:function(card,player){
			var subtype=get.subtype(card,player);
			if(subtype.startsWith('equip')) return parseInt(subtype[5]);
			return 0;
		},
		name:function(card,player){
			if(get.itemtype(player)=='player'||(player!==false&&get.position(card)=='h')){
				var owner=player||get.owner(card);
				if(owner){
					return game.checkMod(card,owner,card.name,'cardname',owner);
				}
			}
			return card.name;
		},
		suit:function(card,player){
			if(!card) return;
			if(Array.isArray(card)){
				if(card.length==1) return get.suit(card[0],player);
				return 'none';
			}
			else if(!card.hasOwnProperty('suit')&&Array.isArray(card.cards)){
				return get.suit(card.cards,player);
			}
			else{
				if(player!==false){
					const owner=player||get.owner(card);
					if(owner){
						return game.checkMod(card,card.suit,'suit',owner);
					}
				}
				if(lib.suits.contains(card.suit)) return card.suit;
				return 'none';
			}
		},
		color:function(card,player){
			if(!card) return;
			if(Array.isArray(card)){
				if(!card.length) return 'none';
				const color=get.color(card[0],player);
				for(let i=1;i<card.length;i++){
					if(get.color(card[i],player)!=color) return 'none';
				}
				return color;
			}
			else if(Object.keys(lib.color).includes(card.color)){
				return card.color;
			}
			else if(Array.isArray(card.cards)&&!lib.suit.includes(card.suit)){
				return get.color(card.cards,player);
			}
			else{
				const suit=get.suit(card,player);
				for(let i in lib.color){
					if(lib.color[i].includes(suit)) return i;
				}
				return 'none';
			}
		},
		number:function(card,player){
			if(!card) return;
			//狗卡你是真敢出啊
			var number=null;
			if(card.hasOwnProperty('number')){
				number=card.number;
				if(typeof number!='number') number=null;
			}
			else{
				if(card.cards&&card.cards.length==1) number=get.number(card.cards[0],false);
			}
			if(player!==false){
				var owner=player||get.owner(card);
				if(owner){
					return game.checkMod(card,owner,number,'cardnumber',owner);
				}
			}
			return number;
		},
		//返回一张杀的属性。如有多种属性则用 lib.natureSeparator 分割开来。例:火雷【杀】的返回值为 fire|thunder
		nature:function(card,player){
			if(typeof card=='string') return card.split(lib.natureSeparator).sort(lib.sort.nature).join(lib.natureSeparator);
			if(Array.isArray(card)) return card.sort(lib.sort.nature).join(lib.natureSeparator);
			var nature=card.nature;
			if(get.itemtype(player)=='player'||player!==false){
				var owner=get.owner(card);
				if(owner){
					return game.checkMod(card,owner,nature,'cardnature',owner);
				}
			}
			return nature;
		},
		//返回包含所有属性的数组
		natureList:function(card,player){
			if(!card) return [];
			if(get.itemtype(card)=='natures') return card.split(lib.natureSeparator);
			if(get.itemtype(card)=='nature') return [card];
			var natures=get.nature.apply(this,arguments);
			if(typeof natures!='string') return [];
			return natures.split(lib.natureSeparator);
		},
		cards:function(num,putBack){
			if(_status.waitingForCards){
				ui.create.cards.apply(ui.create,_status.waitingForCards);
				delete _status.waitingForCards;
			}
			var list=[];
			var card=false;
			if(typeof num!='number') num=1;
			if(num==0) {card=true;num=1;}
			if(num<0) num=1;
			while(num--){
				if(ui.cardPile.hasChildNodes()==false){
					game.washCard();
				}
				if(ui.cardPile.hasChildNodes()==false){
					game.over('平局');
					return [];
				}
				var cardx=ui.cardPile.removeChild(ui.cardPile.firstChild);
				cardx.original='c';
				list.push(cardx);
			}
			if(putBack){
				for(let i=list.length-1;i>=0;i--){
					ui.cardPile.insertBefore(list[i],ui.cardPile.firstChild);
				}
			}
			game.updateRoundNumber();
			if(card) return list[0];
			return list;
		},
		judge:function(card){
			if(card.viewAs) return lib.card[card.viewAs].judge;
			return get.info(card).judge;
		},
		judge2:function(card){
			if(card.viewAs) return lib.card[card.viewAs].judge2;
			return get.info(card).judge2;
		},
		distance:function(from,to,method){
			if(from==to) return 0;
			if(!game.players.contains(from)&&!game.dead.contains(from)) return Infinity;
			if(!game.players.contains(to)&&!game.dead.contains(to)) return Infinity;
			let n=1;
			if(game.chess){
				let fxy=from.getXY(),txy=to.getXY();
				n=Math.abs(fxy[0]-txy[0])+Math.abs(fxy[1]-txy[1]);
				if(method=='raw'||method=='pure'||method=='absolute') return n;
			}
			else if(to.isMin(true)||from.isMin(true)){
				if(method=='raw'||method=='pure'||method=='absolute') return n;
			}
			else{
				let player=from,length=game.players.length;
				const totalPopulation=game.players.length+game.dead.length+1;
				for(let iwhile=0;iwhile<totalPopulation;iwhile++){
					if(player.nextSeat!=to){
						player=player.nextSeat;
						if(player.isAlive()&&!player.isOut()&&!player.hasSkill('undist')&&!player.isMin(true)) n++;
					}
					else{
						break;
					}
				}
				for(let i=0;i<game.players.length;i++){
					if(game.players[i].isOut()||game.players[i].hasSkill('undist')||game.players[i].isMin(true)) length--;
				}
				if(method=='absolute') return n;
				if(from.isDead()) length++;
				if(to.isDead()) length++;
				const left=from.hasSkillTag('left_hand'),right=from.hasSkillTag('right_hand');
				if(left===right) n=Math.min(n,length-n);
				else if(left==true) n=length-n;
				if(method=='raw'||method=='pure') return n;
			}
			n=game.checkMod(from,to,n,'globalFrom',from);
			n=game.checkMod(from,to,n,'globalTo',to);
			const equips1=from.getCards('e',function(card){
				return !ui.selected.cards||!ui.selected.cards.contains(card);
			}),equips2=to.getCards('e',function(card){
				return !ui.selected.cards||!ui.selected.cards.contains(card);
			});
			for(let i=0;i<equips1.length;i++){
				let info=get.info(equips1[i]).distance;
				if(!info) continue;
				if(info.globalFrom){
					n+=info.globalFrom;
				}
			}
			for(let i=0;i<equips2.length;i++){
				let info=get.info(equips2[i]).distance;
				if(!info) continue;
				if(info.globalTo){
					n+=info.globalTo;
				}
				if(info.attaclTo){
					m+=info.attaclTo;
				}
			}
			if(method=='attack'){
				let m=n;
				m=game.checkMod(from,to,m,'attackFrom',from);
				m=game.checkMod(from,to,m,'attackTo',to);
				return m;
				const attakRange=from.getEquipRange();
				m+=(1-attakRange);
				for(let i=0;i<equips2.length;i++){
					let info=get.info(equips2[i]).distance;
					if(!info) continue;
					if(info.attaclTo){
						m+=info.attaclTo;
					}
				}
				return n;
			}
			else if(method=='unchecked') return n;
			return Math.max(1,n);
		},
		info:function(item,player){
			if(typeof item=='string'){
				return lib.skill[item];
			}
			if(typeof item=='object'){
				var name=item.name;
				if(player!==false) name=get.name(item,player);
				return lib.card[name];
			}
		},
		select:function(select){
			if(typeof select=='number') return [select,select];
			if(get.itemtype(select)=='select') return select;
			if(typeof select=='function') return get.select(select());
			return [1,1]
		},
		card:function(original){
			if(_status.event.skill){
				var card=get.info(_status.event.skill).viewAs;
				if(typeof card=='function') card=card(ui.selected.cards,_status.event.player);
				if(card){
					return get.autoViewAs(card,ui.selected.cards);
				}
			}
			if(_status.event._get_card){
				return _status.event._get_card;
			}
			var card=ui.selected.cards[0];
			if(original) return card;
			if(card){
				card=get.autoViewAs(card,ui.selected.cards);
			}
			return card;
		},
		player:function(){
			return _status.event.player;
		},
		players:function(sort,dead,out){
			var players=game.players.slice(0);
			if(sort!=false){
				if(typeof sort=='function'){
					players.sort(sort);
				}
				else{
					if(get.itemtype(sort)!='player') lib.tempSortSeat=_status.event.player;
					else lib.tempSortSeat=sort;
					players.sort(lib.sort.seat);
					delete lib.tempSortSeat;
				}
			}
			if(dead) players=players.concat(game.dead);
			if(!out){
				for(var i=0;i<players.length;i++){
					if(players[i].isOut()) players.splice(i--,1);
				}
			}
			return players;
		},
		position:function(card,ordering){
			if(get.itemtype(card)=='player') return parseInt(card.dataset.position);
			if(card.timeout&&card.destiny&&card.destiny.classList){
				if(card.destiny.classList.contains('equips')) return 'e';
				if(card.destiny.classList.contains('judges')) return 'j';
				if(card.destiny.classList.contains('expansions')) return 'x';
				if(card.destiny.classList.contains('handcards')) return card.classList.contains('glows')?'s':'h';
				if(card.destiny.id=='cardPile') return 'c';
				if(card.destiny.id=='discardPile') return 'd';
				if(card.destiny.id=='special') return 's';
				if(card.destiny.id=='ordering') return ordering?'o':'d';
				return null;
			}
			if(!card.parentNode||!card.parentNode.classList) return;
			if(card.parentNode.classList.contains('equips')) return 'e';
			if(card.parentNode.classList.contains('judges')) return 'j';
			if(card.parentNode.classList.contains('expansions')) return 'x';
			if(card.parentNode.classList.contains('handcards')) return card.classList.contains('glows')?'s':'h';
			if(card.parentNode.id=='cardPile') return 'c';
			if(card.parentNode.id=='discardPile') return 'd';
			if(card.parentNode.id=='special') return 's';
			if(card.parentNode.id=='ordering') return ordering?'o':'d';
			return null;
		},
		skillTranslation:function(str,player){
			var str2;
			if(str.startsWith('re')){
				str2=str.slice(2);
				if(str2){
					if(lib.translate[str]==lib.translate[str2]){
						if(player.hasSkill(str2)){
							return '界'+lib.translate[str];
						}
					}
				}
			}
			else if(str.startsWith('xin')){
				str2=str.slice(3);
				if(str2){
					if(lib.translate[str]==lib.translate[str2]){
						if(player.hasSkill(str2)){
							return '新'+lib.translate[str];
						}
					}
				}
			}
			return get.translation(str);
		},
		skillInfoTranslation:function(name,player){
			if(player&&lib.dynamicTranslate[name]) return lib.dynamicTranslate[name](player,name);
			var str=lib.translate[name+'_info'];
			if(!str) return '';
			return str;
			// return str.replace(/锁定技/g,'<span class="yellowtext">锁定技</span>').
			// 	replace(/限定技/g,'<span class="yellowtext">限定技</span>').
			// 	replace(/觉醒技/g,'<span class="greentext">觉醒技</span>').
			// 	replace(/主将技/g,'<span class="bluetext">主将技</span>').
			// 	replace(/副将技/g,'<span class="bluetext">副将技</span>').
			// 	replace(/阵法技/g,'<span class="bluetext">阵法技</span>').
			// 	replace(/主公技/g,'<span class="firetext">主公技</span>');
		},
		translation:function(str,arg){
			if(str&&typeof str=='object'&&(str.name||str._tempTranslate)){
				if(str._tempTranslate) return str._tempTranslate;
				var str2;
				if(arg=='viewAs'&&str.viewAs){
					str2=get.translation(str.viewAs);
				}
				else{
					str2=get.translation(str.name);
				}
				if(str2=='杀'){
					str2='';
					if(typeof str.nature=='string'){
						let natures=str.nature.split(lib.natureSeparator).sort(lib.sort.nature);
						for(let nature of natures){
							str2+=lib.translate['nature_'+nature]||lib.translate[nature]||'';
						}
					}
					str2+='杀';
				}
				if(get.itemtype(str)=='card'||str.isCard){
					if(_status.cardtag&&str.cardid){
						var tagstr='';
						for(var i in _status.cardtag){
							if(_status.cardtag[i].contains(str.cardid)){
								tagstr+=lib.translate[i+'_tag'];
							}
						}
						if(tagstr){
							str2+='·'+tagstr;
						}
					}
					if(str.suit&&str.number){
						var cardnum=str.number||'';
						if([1,11,12,13].contains(cardnum)){
							cardnum={'1':'A','11':'J','12':'Q','13':'K'}[cardnum]
						}
						if(arg=='viewAs'&&str.viewAs!=str.name&&str.viewAs){
							str2+='('+get.translation(str)+')';
						}
						else{
							str2+='【'+get.translation(str.suit)+cardnum+'】';
							// var len=str2.length-1;
							// str2=str2.slice(0,len)+'<span style="letter-spacing: -2px">'+str2[len]+'·</span>'+get.translation(str.suit)+str.number;
						}
					}
				}
				return str2;
			}
			if(Array.isArray(str)){
				var str2=get.translation(str[0],arg);
				for(var i=1;i<str.length;i++){
					str2+='、'+get.translation(str[i],arg);
				}
				return str2;
			}
			if(get.itemtype(str)=='natures'){
				let natures=str.split(lib.natureSeparator).sort(lib.sort.nature);
				var str2='';
				for(var nature of natures){
					str2+=lib.translate['nature_'+nature]||lib.translate[nature]||'';
				}
				return str2;
			}
			if(arg=='skill'){
				if(lib.translate[str+'_ab']) return lib.translate[str+'_ab'];
				if(lib.translate[str]) return lib.translate[str].slice(0,2);
				return str;
			}
			else if(arg=='info'){
				if(lib.translate[str+'_info']) return lib.translate[str+'_info'];
				var str2=str.slice(0,str.length-1);
				if(lib.translate[str2+'_info']) return lib.translate[str2+'_info'];
				if(str.lastIndexOf('_')>0){
					str2=str.slice(0,str.lastIndexOf('_'));
					if(lib.translate[str2+'_info']) return lib.translate[str2+'_info'];
				}
				str2=str.slice(0,str.length-2);
				if(lib.translate[str2+'_info']) return lib.translate[str2+'_info'];
				if(lib.skill[str]&&lib.skill[str].prompt) return lib.skill[str].prompt;
			}
			if(lib.translate[str]){
				return lib.translate[str];
			}
			if(typeof str=='string'){
				if(lib.translate['nature_'+str]) return lib.translate['nature_'+str];
				return str;
			}
			if(typeof str=='number'||typeof str=='boolean'){
				return str.toString();
			}
			if(str&&str.toString){
				return str.toString();
			}
			return '';
		},
		strNumber:function(num){
			switch(num){
				case 1:return 'A';
				case 11:return 'J';
				case 12:return 'Q';
				case 13:return 'K';
				default:return num.toString();
			}
		},
		cnNumber:function(num,two){
			if(num==Infinity) return '∞';
			if(isNaN(num)) return '';
			if(typeof num!='number') return num;
			if(num<0||num>99) return num;
			if(num<=10){
				switch(num){
					case 0:return '〇';
					case 1:return '一';
					case 2:return two?'二':'两';
					case 3:return '三';
					case 4:return '四';
					case 5:return '五';
					case 6:return '六';
					case 7:return '七';
					case 8:return '八';
					case 9:return '九';
					case 10:return '十';
				}
			}
			if(num<20){
				return '十'+get.cnNumber(num-10,true);
			}
			var x=Math.floor(num/10);
			return get.cnNumber(x,true)+'十'+(num>10*x?get.cnNumber(num-10*x,true):'');
		},
		selectableButtons:function(sort){
			if(!_status.event.player) return[];
			var buttons=_status.event.dialog.buttons;
			var selectable=[];
			for(var i=0;i<buttons.length;i++){
				if(buttons[i].classList.contains('selectable')&&
					buttons[i].classList.contains('selected')==false){
					selectable.push(buttons[i]);
				}
			}
			if(sort){
				selectable.sort(sort);
			}
			return selectable;
		},
		selectableCards:function(sort){
			if(!_status.event.player) return[];
			var cards=_status.event.player.getCards('hes');
			var selectable=[];
			for(var i=0;i<cards.length;i++){
				if(cards[i].classList.contains('selectable')&&
					cards[i].classList.contains('selected')==false){
					selectable.push(cards[i]);
				}
			}
			if(sort){
				selectable.sort(sort);
			}
			return selectable;
		},
		skills:function(){
			var skills=[];
			if(ui.skills){
				skills=skills.concat(ui.skills.skills);
			}
			if(ui.skills2){
				skills=skills.concat(ui.skills2.skills);
			}
			if(ui.skills3){
				skills=skills.concat(ui.skills3.skills);
			}
			return skills;
		},
		gainableSkills:function(func,player){
			var list=[];
			for(var i in lib.character){
				if(lib.filter.characterDisabled(i)) continue;
				if(lib.filter.characterDisabled2(i)) continue;
				if(lib.character[i][4]){
					if(lib.character[i][4].contains('boss')) continue;
					if(lib.character[i][4].contains('hiddenboss')) continue;
					if(lib.character[i][4].contains('minskin')) continue;
					if(lib.character[i][4].contains('unseen')) continue;
				}
				for(var j=0;j<lib.character[i][3].length;j++){
					var skill=lib.character[i][3][j];
					var info=lib.skill[skill];
					if(lib.filter.skillDisabled(skill)) continue;
					if(func&&!func(info,skill,i)) continue;
					if(player&&player.hasSkill&&info.ai&&info.ai.combo&&!player.hasSkill(info.ai.combo)) continue;
					list.add(skill);
				}
			}
			return list;
		},
		gainableSkillsName:function(name, func){
			var list=[];
			if(name&&lib.character[name]){
				if(lib.character[name][4]){
					if(lib.character[name][4].contains('boss')) return list;
					if(lib.character[name][4].contains('hiddenboss')) return list;
					if(lib.character[name][4].contains('minskin')) return list;
					if(lib.character[name][4].contains('unseen')) return list;
				}
				for(var j=0;j<lib.character[name][3].length;j++){
					var skill=lib.character[name][3][j];
					var info=lib.skill[skill];
					if(lib.filter.skillDisabled(skill)) continue;
					if(func&&!func(info,skill,name)) continue;
					list.add(skill);
				}
			}
			return list;
		},
		gainableCharacters:function(func){
			var list=[];
			for(var i in lib.character){
				var info=lib.character[i];
				if(!info) continue;
				if(typeof func=='function'&&!func(info,i)) continue;
				if(lib.filter.characterDisabled(i)) continue;
				if(lib.filter.characterDisabled2(i)) continue;
				list.push(i);
			}
			if(func===true){
				var players=game.players.concat(game.dead);
				for(var i=0;i<players.length;i++){
					list.remove(players[i].name);
					list.remove(players[i].name1);
					list.remove(players[i].name2);
				}
			}
			return list;
		},
		selectableTargets:function(sort){
			var selectable=[];
			var players=game.players.slice(0);
			if(_status.event.deadTarget) players.addArray(game.dead);
			for(var i=0;i<players.length;i++){
				if(players[i].classList.contains('selectable')&&
					players[i].classList.contains('selected')==false){
					selectable.push(players[i]);
				}
			}
			selectable.randomSort();
			if(sort){
				selectable.sort(sort);
			}
			return selectable;
		},
		filter:function(filter,i){
			if(typeof filter=='function') return filter;
			if(i==undefined) i=0;
			var result=function(){
				if(filter==arguments[i]) return true;
				for(var j in filter){
					if(filter.hasOwnProperty(j)){
						if(get.itemtype(arguments[i])=='card'){
							if(j=='name'){
								if(Array.isArray(filter[j])){
									if(filter[j].contains(get.name(arguments[i]))==false) return false;
								}
								else if(typeof filter[j]=='string'){
									if(get.name(arguments[i])!=filter[j]) return false;
								}
							}
							else if(j=='type'){
								if(Array.isArray(filter[j])){
									if(filter[j].contains(get.type(arguments[i]))==false) return false;
								}
								else if(typeof filter[j]=='string'){
									if(get.type(arguments[i])!=filter[j]) return false;
								}
							}
							else if(j=='subtype'){
								if(Array.isArray(filter[j])){
									if(filter[j].contains(get.subtype(arguments[i]))==false) return false;
								}
								else if(typeof filter[j]=='string'){
									if(get.subtype(arguments[i])!=filter[j]) return false;
								}
							}
							else if(j=='color'){
								if(Array.isArray(filter[j])){
									if(filter[j].contains(get.color(arguments[i]))==false) return false;
								}
								else if(typeof filter[j]=='string'){
									if(get.color(arguments[i])!=filter[j]) return false;
								}
							}
							else if(j=='suit'){
								if(Array.isArray(filter[j])){
									if(filter[j].contains(get.suit(arguments[i]))==false) return false;
								}
								else if(typeof filter[j]=='string'){
									if(get.suit(arguments[i])!=filter[j]) return false;
								}
							}
							else if(j=='number'){
								if(Array.isArray(filter[j])){
									if(filter[j].contains(get.number(arguments[i]))==false) return false;
								}
								else if(typeof filter[j]=='string'){
									if(get.number(arguments[i])!=filter[j]) return false;
								}
							}
							else if(Array.isArray(filter[j])){
								if(filter[j].contains(arguments[i][j])==false) return false;
							}
							else if(typeof filter[j]=='string'){
								if(arguments[i][j]!=filter[j]) return false;
							}
						}
						else{
							if(arguments[i][j]!=filter[j]) return false;
						}
					}
				}
				return true;
			}
			result._filter_args=[filter,i];
			return result;
		},
		cardCount:function(card,player){
			var num;
			if(card==true){
				num=0;
				var stat=player.getStat('card');
				for(var i in stat){
					if(typeof stat[i]=='number') num+=stat[i];
				}
				return num;
			}
			if(player==undefined) player=_status.event.player;
			if(typeof card=='object'){
				card=card.name;
			}
			num=player.getStat('card')[card];
			if(num==undefined) return 0;
			return num;
		},
		skillCount:function(skill,player){
			if(player==undefined) player=_status.event.player;
			var num=player.getStat('skill')[skill];
			if(num==undefined) return 0;
			return num;
		},
		owner:function(card,method){
			var list=game.players.concat(game.dead);
			for(var i=0;i<list.length;i++){
				if(list[i].getCards('hejsx').contains(card)) return list[i];
				if(list[i].judging[0]==card&&method!='judge') return list[i];
			}
			//for(var i=0;i<game.players.length;i++){
			//	if(game.players[i].using&&game.players[i].using.contains(card)) return game.players[i];
			//}
		},
		noSelected:function(){
			return (ui.selected.buttons.length+ui.selected.cards.length+ui.selected.targets.length==0)
		},
		population:function(identity){
			if(identity==undefined) return game.players.length+game.dead.length;
			var i;
			var num=0;
			for(i=0;i<game.players.length;i++){
				if(game.players[i].identity==identity) num++;
			}
			return num;
		},
		totalPopulation:function(identity){
			if(identity==undefined) return game.players.length+game.dead.length;
			var i,players=game.players.concat(game.dead);
			var num=0;
			for(i=0;i<players.length;i++){
				if(players[i].identity==identity) num++;
			}
			return num;
		},
		cardtag:function(item,tag){
			if(item.cardid&&(get.itemtype(item)=='card'||!item.cards||!item.cards.length||item.name==item.cards[0].name)&&_status.cardtag&&_status.cardtag[tag]&&_status.cardtag[tag].contains(item.cardid)){
				return true;
			}
			if(item.cardtags&&item.cardtags.contains(tag)) return true;
			return false;
		},
		tag:function(item,tag,item2,bool){
			var result;
			if(get.info(item)&&get.info(item).ai&&get.info(item).ai.tag){
				result=get.info(item,bool).ai.tag[tag];
			}
			if(typeof result=='function') return result(item,item2);
			return result;
		},
		sortCard:function(sort){
			var func;
			if(sort=='type_sort'){
				func=function(card){
					var type=get.type(card,null,false);
					var subtype=get.subtype(card,false);
					if(lib.cardType[subtype]){
						return lib.cardType[subtype];
					}
					if(lib.cardType[type]){
						return lib.cardType[type];
					}
					switch(type){
						case 'basic':return 2;
						case 'chess':return 1.5;
						case 'trick':return -1;
						case 'delay':return -2;
						case 'equip':return -3;
						default:return -4;
					}
				}
			}
			else if(sort=='suit_sort'){
				func=function(card){
					if(get.suit(card)=='heart') return 2;
					if(get.suit(card)=='diamond') return 1;
					if(get.suit(card)=='spade') return -1;
					if(get.suit(card)=='club') return -2;
				}
			}
			else if(sort=='number_sort'){
				func=function(card){
					return get.number(card)-7+0.5;
				}
			}
			return func;
		},
		difficulty:function(){
			switch(get.config('difficulty')){
				case 'easy':return 1;
				case 'normal':return 2;
				case 'hard':return 3;
				default: return 1;
			}
		},
		cardPile:function(name,create){
			var filter=function(card){
				if(typeof name=='string'){
					if(card.name==name){
						return true;
					}
				}
				else if(typeof name=='function'){
					if(name(card)){
						return true;
					}
				}
				return false;
			};
			if(create!='discardPile'){
				var num=get.rand(0,ui.cardPile.childNodes.length-1);
				for(var i=0;i<ui.cardPile.childNodes.length;i++){
					var j=i;
					if(j>=ui.cardPile.childNodes.length) j-=ui.cardPile.childNodes.length;
					if(filter(ui.cardPile.childNodes[j])){
						return ui.cardPile.childNodes[j];
					}
				}
			}
			if(create!='cardPile'){
				for(var i=0;i<ui.discardPile.childNodes.length;i++){
					var j=i;
					if(j>=ui.discardPile.childNodes.length) j-=ui.discardPile.childNodes.length;
					if(filter(ui.discardPile.childNodes[j])){
						return ui.discardPile.childNodes[j];
					}
				}
			}
			if(create=='field'){
				var found=null;
				game.findPlayer(function(current){
					var ej=current.getCards('ej');
					for(var i=0;i<ej.length;i++){
						if(filter(ej[i])){
							found=ej[i];
							return true;
						}
					}
				});
				return found;
			}
			if(create&&!['cardPile','discardPile','field'].contains(create)){
				return game.createCard(name);
			}
			return null;
		},
		cardPile2:function(name){
			return get.cardPile(name,'cardPile');
		},
		discardPile:function(name){
			return get.cardPile(name,'discardPile');
		},
		aiStrategy:function(){
			switch(get.config('ai_strategy')){
				case 'ai_strategy_1':return 1;
				case 'ai_strategy_2':return 2;
				case 'ai_strategy_3':return 3;
				case 'ai_strategy_4':return 4;
				case 'ai_strategy_5':return 5;
				case 'ai_strategy_6':return 6;
				default: return 1;
			}
		},
		skillintro:function(name,learn,learn2){
			var str='';
			var infoitem=lib.character[name];
			if(!infoitem){
				for(var itemx in lib.characterPack){
					if(lib.characterPack[itemx][name]){
						infoitem=lib.characterPack[itemx][name];break;
					}
				}
			}
			var skills=infoitem[3];
			var opacity;
			for(var i=0;i<skills.length;i++){
				if(lib.translate[skills[i]]&&lib.translate[skills[i]+'_info']&&lib.skill[skills[i]]){
					if(learn&&lib.skill[skills[i]].unique&&(learn2||!lib.skill[skills[i]].gainable)){
						opacity='opacity:0.5';
					}
					else{
						opacity='';
					}
					var skilltrans=get.translation(skills[i]).slice(0,2);
					str+='<div class="skill" style="'+opacity+
					'">【'+skilltrans+'】</div><div style="'+opacity+'">'+
					get.skillInfoTranslation(skills[i])+'</div><div style="display:block;height:10px"></div>';
				}
			}
			return str;
		},
		intro:function(name){
			var info=lib.character[name];
			var str='性别:'+get.translation(info[0])+'<br/>';
			str+='势力:'+get.translation(info[1])+'<br/>';
			str+='体力:'+get.translation(info[2])+'<br/>';
			str+='技能:';
			if(info[3].length){
				str+=get.translation(info[3][0]);
				for(var i=1;i<info[3].length;i++){
					str+='、'+get.translation(info[3][i]);
				}
			}
			return str;
		},
		storageintro:function(type,content,player,dialog,skill){
			switch(type){
				case 'mark':{
					if(content>0){
						return '共有'+content+'个标记';
					}
					return false;
				}
				case 'turn':{
					if(content>0){
						return '剩余'+content+'个回合';
					}
					return false;
				}
				case 'time':{
					if(content>0){
						return '剩余'+content+'次';
					}
					return false;
				}
				case 'limited':{
					if(content){
						return '已发动';
					}
					return '未发动';
				}
				case 'info':{
					return lib.translate[skill+'_info'];
				}
				case 'cardCount':{
					if(Array.isArray(content)){
						return '共有'+get.cnNumber(content.length)+'张牌';
					}
					return false;
				}
				case 'expansion':{
					content=player.getCards('x',function(card){
						return card.hasGaintag(skill);
					});
					if(dialog&&content.length){
						dialog.addAuto(content);
					}
					else{
						return '没有卡牌';
					}
					return false;
				}
				case 'card':case 'cards':{
					if(get.itemtype(content)=='card'){
						content=[content];
					}
					if(dialog&&get.itemtype(content)=='cards'){
						dialog.addAuto(content);
					}
					else{
						if(content&&content.length){
							return get.translation(content);
						}
					}
					if(Array.isArray(content)&&!content.length){
						return '没有卡牌';
					}
					return false;
				}
				case 'player':case 'players':{
					if(get.itemtype(content)=='player'){
						content=[content];
					}
					if(dialog&&get.itemtype(content)=='players'){
						dialog.addAuto(content);
						return false;
					}
					else{
						if(content&&content.length){
							return get.translation(content);
						}
						return false;
					}
				}
				case 'character':case 'characters':{
					if(typeof content=='string'){
						content=[content];
					}
					if(dialog&&Array.isArray(content)){
						dialog.addAuto([content,'character']);
						return false;
					}
					else{
						if(content&&content.length){
							return get.translation(content);
						}
						return false;
					}
				}
				default:{
					if(typeof type=='string'){
						type=type.replace(/#/g,content);
						type=type.replace(/&/g,get.cnNumber(content));
						type=type.replace(/\$/g,get.translation(content));
						return type;
					}
					else if(typeof type=='function'){
						return type(content,player,skill);
					}
					return false;
				}
			}
		},
		nodeintro:function(node,simple,evt){
			var uiintro=ui.create.dialog('hidden','notouchscroll');
			if(node.classList.contains('player')&&!node.name){
				return uiintro;
			}
			var i,translation,intro,str;
			if(node._nointro) return;
			if(typeof node._customintro=='function'){
				if(node._customintro(uiintro,evt)===false) return;
				lib.placePoppedDialog(uiintro,evt);
			}
			else if(Array.isArray(node._customintro)){
				var caption=node._customintro[0];
				var content=node._customintro[1];
				if(typeof caption=='function'){
					caption=caption(node);
				}
				if(typeof content=='function'){
					content=content(node);
				}
				uiintro.add(caption);
				uiintro.add('<div class="text center" style="padding-bottom:5px">'+content+'</div>');
			}
			else if(node.classList.contains('player')||node.linkplayer){
				if(node.linkplayer){
					node=node.link;
				}
				let capt=get.translation(node.name);
				const characterInfo=get.character(node.name),sex=node.sex||characterInfo[0];
				if(sex&&sex!='unknown'&&lib.config.show_sex) capt+=`&nbsp;&nbsp;${sex=='none'?'无':get.translation(sex)}`;
				const group=node.group;
				if(group&&group!='unknown'&&lib.config.show_group) capt+=`&nbsp;&nbsp;${get.translation(group)}`;
				uiintro.add(capt);

				if(lib.characterTitle[node.name]){
					uiintro.addText(get.colorspan(lib.characterTitle[node.name]));
				}

				if(!node.noclick){
					const allShown=(node.isUnderControl()||(!game.observe&&game.me&&game.me.hasSkillTag('viewHandcard',null,node,true)));
					const shownHs=node.getShownCards();
					if(shownHs.length){
						uiintro.add('<div class="text center">明置的手牌</div>');
						uiintro.addSmall(shownHs);
						if(allShown){
							var hs=node.getCards('h');
							hs.removeArray(shownHs)
							if(hs.length){
								uiintro.add('<div class="text center">其他手牌</div>');
								uiintro.addSmall(hs);
							}
						}
					}
					else if(allShown){
						var hs=node.getCards('h');
						if(hs.length){
							uiintro.add('<div class="text center">手牌</div>');
							uiintro.addSmall(hs);
						}
					}
				}

				var skills=node.getSkills(null,false,false).slice(0);
				var skills2=game.filterSkills(skills,node);
				if(node==game.me&&node.hiddenSkills.length){
					skills.addArray(node.hiddenSkills);
				}
				for(var i in node.disabledSkills){
					if(node.disabledSkills[i].length==1&&
						node.disabledSkills[i][0]==i+'_awake'&&
						!node.hiddenSkills.contains(i)){
						skills.add(i);
					}
				}
				for(i=0;i<skills.length;i++){
					if(lib.skill[skills[i]]&&(lib.skill[skills[i]].nopop||lib.skill[skills[i]].equipSkill)) continue;
					if(lib.translate[skills[i]+'_info']){
						translation=lib.translate[skills[i]+'_ab']||get.translation(skills[i]).slice(0,2);
						if(node.forbiddenSkills[skills[i]]){
							var forbidstr='<div style="opacity:0.5"><div class="skill">【'+translation+'】</div><div>';
							if(node.forbiddenSkills[skills[i]].length){
								forbidstr+='(与'+get.translation(node.forbiddenSkills[skills[i]])+'冲突)<br>';
							}
							else{
								forbidstr+='(双将禁用)<br>';
							}
							forbidstr+=get.skillInfoTranslation(skills[i],node)+'</div></div>'
							uiintro.add(forbidstr);
						}
						else if(!skills2.contains(skills[i])){
							if(lib.skill[skills[i]].preHidden&&get.mode()=='guozhan'){
								uiintro.add('<div><div class="skill" style="opacity:0.5">【'+translation+'】</div><div><span style="opacity:0.5">'+get.skillInfoTranslation(skills[i],node)+'</span><br><div class="underlinenode on gray" style="position:relative;padding-left:0;padding-top:7px">预亮技能</div></div></div>');
								var underlinenode=uiintro.content.lastChild.querySelector('.underlinenode');
								if(_status.prehidden_skills.contains(skills[i])){
									underlinenode.classList.remove('on');
								}
								underlinenode.link=skills[i];
								underlinenode.listen(ui.click.hiddenskill);
							}
							else uiintro.add('<div style="opacity:0.5"><div class="skill">【'+translation+'】</div><div>'+get.skillInfoTranslation(skills[i],node)+'</div></div>');
						}
						else if(lib.skill[skills[i]].temp||!node.skills.contains(skills[i])||lib.skill[skills[i]].thundertext){
							if(lib.skill[skills[i]].frequent||lib.skill[skills[i]].subfrequent){
								uiintro.add('<div><div class="skill thundertext thunderauto">【'+translation+'】</div><div class="thundertext thunderauto">'+get.skillInfoTranslation(skills[i],node)+'<br><div class="underlinenode on gray" style="position:relative;padding-left:0;padding-top:7px">自动发动</div></div></div>');
								var underlinenode=uiintro.content.lastChild.querySelector('.underlinenode');
								if(lib.skill[skills[i]].frequent){
									if(lib.config.autoskilllist.contains(skills[i])){
										underlinenode.classList.remove('on');
									}
								}
								if(lib.skill[skills[i]].subfrequent){
									for(var j=0;j<lib.skill[skills[i]].subfrequent.length;j++){
										if(lib.config.autoskilllist.contains(skills[i]+'_'+lib.skill[skills[i]].subfrequent[j])){
											underlinenode.classList.remove('on');
										}
									}
								}
								if(lib.config.autoskilllist.contains(skills[i])){
									underlinenode.classList.remove('on');
								}
								underlinenode.link=skills[i];
								underlinenode.listen(ui.click.autoskill2);
							}
							else{
								uiintro.add('<div><div class="skill thundertext thunderauto">【'+translation+'】</div><div class="thundertext thunderauto">'+get.skillInfoTranslation(skills[i],node)+'</div></div>');
							}
						}
						else if(lib.skill[skills[i]].frequent||lib.skill[skills[i]].subfrequent){
							uiintro.add('<div><div class="skill">【'+translation+'】</div><div>'+get.skillInfoTranslation(skills[i],node)+'<br><div class="underlinenode on gray" style="position:relative;padding-left:0;padding-top:7px">自动发动</div></div></div>');
							var underlinenode=uiintro.content.lastChild.querySelector('.underlinenode');
							if(lib.skill[skills[i]].frequent){
								if(lib.config.autoskilllist.contains(skills[i])){
									underlinenode.classList.remove('on');
								}
							}
							if(lib.skill[skills[i]].subfrequent){
								for(var j=0;j<lib.skill[skills[i]].subfrequent.length;j++){
									if(lib.config.autoskilllist.contains(skills[i]+'_'+lib.skill[skills[i]].subfrequent[j])){
										underlinenode.classList.remove('on');
									}
								}
							}
							if(lib.config.autoskilllist.contains(skills[i])){
								underlinenode.classList.remove('on');
							}
							underlinenode.link=skills[i];
							underlinenode.listen(ui.click.autoskill2);
						}
						else if(lib.skill[skills[i]].clickable&&node.isIn()&&node.isUnderControl(true)){
							var intronode=uiintro.add('<div><div class="skill">【'+translation+'】</div><div>'+get.skillInfoTranslation(skills[i],node)+'<br><div class="menubutton skillbutton" style="position:relative;margin-top:5px">点击发动</div></div></div>').querySelector('.skillbutton');
							if(!_status.gameStarted||(lib.skill[skills[i]].clickableFilter&&!lib.skill[skills[i]].clickableFilter(node))){
								intronode.classList.add('disabled');
								intronode.style.opacity=0.5;
							}
							else{
								intronode.link=node;
								intronode.func=lib.skill[skills[i]].clickable;
								intronode.classList.add('pointerdiv');
								intronode.listen(ui.click.skillbutton);
							}
						}
						else if(lib.skill[skills[i]].nobracket){
							uiintro.add('<div><div class="skilln">'+get.translation(skills[i])+'</div><div>'+get.skillInfoTranslation(skills[i],node)+'</div></div>');
						}
						else{
							uiintro.add('<div><div class="skill">【'+translation+'】</div><div>'+get.skillInfoTranslation(skills[i],node)+'</div></div>');
						}
						if(lib.translate[skills[i]+'_append']){
							uiintro._place_text=uiintro.add('<div class="text">'+lib.translate[skills[i]+'_append']+'</div>')
						}
					}
				}
				// if(get.is.phoneLayout()){
				//     var storage=node.storage;
				//     for(i in storage){
				//      			if(get.info(i)&&get.info(i).intro){
				//      						 intro=get.info(i).intro;
				//      						 if(node.getSkills().concat(lib.skill.global).contains(i)==false&&!intro.show) continue;
				//      						 var name=intro.name?intro.name:get.translation(i);
				//      						 if(typeof name=='function'){
				//      									  name=name(storage[i],node);
				//      						 }
				//      						 translation='<div><div class="skill">『'+name.slice(0,2)+'』</div><div>';
				//      						 var stint=get.storageintro(intro.content,storage[i],node,null,i);
				//      						 if(stint){
				//      									  translation+=stint+'</div></div>';
				//      									  uiintro.add(translation);
				//      						 }
				//      			}
				//     }
				// }

				if(lib.config.right_range&&_status.gameStarted){
					uiintro.add(ui.create.div('.placeholder'));
					var table,tr,td;
					table=document.createElement('table');
					tr=document.createElement('tr');
					table.appendChild(tr);
					td=document.createElement('td');
					td.innerHTML='距离';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='手牌';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='行动';
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML='伤害';
					tr.appendChild(td);

					tr=document.createElement('tr');
					table.appendChild(tr);
					td=document.createElement('td');
					if(node==game.me||!game.me||!game.me.isIn()){
						td.innerHTML='-';
					}
					else{
						var dist1=get.numStr(Math.max(1,game.me.distanceTo(node)));
						var dist2=get.numStr(Math.max(1,node.distanceTo(game.me)));
						if(dist1==dist2){
							td.innerHTML=dist1;
						}
						else{
							td.innerHTML=dist1+'/'+dist2;
						}
					}
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML=`${node.countCards('h')}/${node.getHandcardLimit()}`;
					tr.appendChild(td);
					td=document.createElement('td');
					td.innerHTML=node.phaseNumber;
					tr.appendChild(td);
					td=document.createElement('td');

					(function(){
						num=0;
						for(var j=0;j<node.stat.length;j++){
							if(typeof node.stat[j].damage=='number') num+=node.stat[j].damage;
						}
						td.innerHTML=num;
					}());
					tr.appendChild(td);
					table.style.width='calc(100% - 20px)';
					table.style.marginLeft='10px';

					uiintro.content.appendChild(table);
					if(!lib.config.show_favourite){
						table.style.paddingBottom='5px'
					}
				}
				if(!simple||get.is.phoneLayout()){
					var es=node.getCards('e');
					for(var i=0;i<es.length;i++){
						var cardinfo=lib.card[es[i].name];
						if(cardinfo&&cardinfo.cardPrompt) uiintro.add('<div><div class="skill">'+es[i].outerHTML+'</div><div>'+cardinfo.cardPrompt(es[i])+'</div></div>');
						else uiintro.add('<div><div class="skill">'+es[i].outerHTML+'</div><div>'+lib.translate[es[i].name+'_info']+'</div></div>');
						uiintro.content.lastChild.querySelector('.skill>.card').style.transform='';
						
						if(lib.translate[es[i].name+'_append']){
							uiintro.add('<div class="text">'+lib.translate[es[i].name+'_append']+'</div>');
						}
					}
					var js=node.getCards('j');
					for(var i=0;i<js.length;i++){
						if(js[i].viewAs&&js[i].viewAs!=js[i].name){
							uiintro.add('<div><div class="skill">'+js[i].outerHTML+'</div><div>'+lib.translate[js[i].viewAs]+':'+lib.translate[js[i].viewAs+'_info']+'</div></div>');
						}
						else{
							uiintro.add('<div><div class="skill">'+js[i].outerHTML+'</div><div>'+lib.translate[js[i].name+'_info']+'</div></div>');
						}
						uiintro.content.lastChild.querySelector('.skill>.card').style.transform='';
					}
					if(get.is.phoneLayout()){
						var markCoutainer=ui.create.div('.mark-container.marks');
						for(var i in node.marks){
							var nodemark=node.marks[i].cloneNode(true);
							nodemark.classList.add('pointerdiv');
							nodemark.link=node.marks[i];
							nodemark.style.transform='';
							markCoutainer.appendChild(nodemark);
							nodemark.listen(function(){
								uiintro.noresume=true;
								var rect=this.link.getBoundingClientRect();
								ui.click.intro.call(this.link,{
									clientX:rect.left+rect.width,
									clientY:rect.top+rect.height/2,
								});
								if(lib.config.touchscreen){
									uiintro._close();
								}
							});
						}
						if(markCoutainer.childElementCount){
							uiintro.addText('标记');
							uiintro.add(markCoutainer);
						}
					}
				}
				if(!game.observe&&_status.gameStarted&&game.me&&node!=game.me){
					ui.throwEmotion=[];
					uiintro.addText('发送交互表情');
					var click=function(){
						if(_status.dragged) return;
						if(_status.justdragged) return;
						if(_status.throwEmotionWait) return;
						var emotion=this.link;
						if(game.online){
							game.send('throwEmotion',node,emotion);
						}
						else game.me.throwEmotion(node,emotion);
						uiintro._close();
						_status.throwEmotionWait=true;
						setTimeout(function(){
							_status.throwEmotionWait=false;
							if(ui.throwEmotion){
								for(var i of ui.throwEmotion) i.classList.remove('exclude');
							}
						},(emotion=='flower'||emotion=='egg')?500:5000)
					};
					var td;
					var table=document.createElement('div');
					table.classList.add('add-setting');
					table.style.margin='0';
					table.style.width='100%';
					table.style.position='relative';
					var listi=['flower','egg'];
					for(var i=0;i<listi.length;i++){
						td=ui.create.div('.menubutton.reduce_radius.pointerdiv.tdnode');
						ui.throwEmotion.add(td);
						if(_status.throwEmotionWait) td.classList.add('exclude');
						td.link=listi[i];
						table.appendChild(td);
						td.innerHTML='<span>'+get.translation(listi[i])+'</span>';
						td.addEventListener(lib.config.touchscreen?'touchend':'click',click);
					}
					uiintro.content.appendChild(table);
					table=document.createElement('div');
					table.classList.add('add-setting');
					table.style.margin='0';
					table.style.width='100%';
					table.style.position='relative';
					var listi=['wine','shoe'];
					if(game.me.storage.zhuSkill_shanli) listi=['yuxisx','jiasuo'];
					for(var i=0;i<listi.length;i++){
						td=ui.create.div('.menubutton.reduce_radius.pointerdiv.tdnode');
						ui.throwEmotion.add(td);
						if(_status.throwEmotionWait) td.classList.add('exclude');
						td.link=listi[i];
						table.appendChild(td);
						td.innerHTML='<span>'+get.translation(listi[i])+'</span>';
						td.addEventListener(lib.config.touchscreen?'touchend':'click',click);
					}
					uiintro.content.appendChild(table);
				}
				var modepack=lib.characterPack['mode_'+get.mode()];
				if(lib.config.show_favourite&&lib.character[node.name]&&game.players.contains(node)&&
					(!modepack||!modepack[node.name])&&(!simple||get.is.phoneLayout())){
					var addFavourite=ui.create.div('.text.center.pointerdiv');
					addFavourite.link=node.name;
					if(lib.config.favouriteCharacter.contains(node.name)){
						addFavourite.innerHTML='移除收藏';
					}
					else{
						addFavourite.innerHTML='添加收藏';
					}
					addFavourite.listen(ui.click.favouriteCharacter)
					uiintro.add(addFavourite);
				}
				if(!simple||get.is.phoneLayout()){
					if((lib.config.change_skin||lib.skin)&&!node.isUnseen()){
						var num=1;
						var introadded=false;
						var createButtons=function(num,avatar2){
							if(!introadded){
								introadded=true;
								uiintro.add('<div class="text center">更改皮肤</div>');
							}
							var buttons=ui.create.div('.buttons.smallzoom.scrollbuttons');
							lib.setMousewheel(buttons);
							var nameskin=(avatar2?node.name2:node.name1);
							var nameskin2=nameskin;
							var gzbool=false;
							if(nameskin.startsWith('gz_shibing')){
								nameskin=nameskin.slice(3,11);
							}
							else if(nameskin.startsWith('gz_')){
								nameskin=nameskin.slice(3);
								gzbool=true;
							}
							for(var i=0;i<=num;i++){
								var button=ui.create.div('.button.character.pointerdiv',buttons,function(){
									if(this._link){
										if(avatar2){
											lib.config.skin[nameskin]=this._link;
											node.node.avatar2.style.backgroundImage=this.style.backgroundImage;
										}
										else{
											lib.config.skin[nameskin]=this._link;
											node.node.avatar.style.backgroundImage=this.style.backgroundImage;
										}
									}
									else{
										delete lib.config.skin[nameskin];
										if(avatar2){
											if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) node.node.avatar2.setBackground(nameskin2,'character');
											else node.node.avatar2.setBackground(nameskin,'character');
										}
										else{
											if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) node.node.avatar.setBackground(nameskin2,'character');
											else node.node.avatar.setBackground(nameskin,'character');
										}
									}
									game.saveConfig('skin',lib.config.skin);
								});
								button._link=i;
								if(i){
									button.setBackgroundImage('image/skin/'+nameskin+'/'+i+'.jpg');
								}
								else{
									if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) button.setBackground(nameskin2,'character','noskin');
									else button.setBackground(nameskin,'character','noskin');
								}
							}
							uiintro.add(buttons);
						};
						var loadImage=function(avatar2){
							var img=new Image();
							img.onload=function(){
								num++;
								loadImage(avatar2);
							}
							img.onerror=function(){
								num--;
								if(num){
									createButtons(num,avatar2);
								}
								if(!avatar2){
									if(!node.classList.contains('unseen2')&&node.name2){
										num=1;
										loadImage(true);
									}
								}
							}
							var nameskin=(avatar2?node.name2:node.name1);
							var nameskin2=nameskin;
							var gzbool=false;
							if(nameskin.startsWith('gz_shibing')){
								nameskin=nameskin.slice(3,11);
							}
							else if(nameskin.startsWith('gz_')){
								nameskin=nameskin.slice(3);
								gzbool=true;
							}
							img.src=lib.assetURL+'image/skin/'+nameskin+'/'+num+'.jpg';
						}
						if(lib.config.change_skin){
							if(!node.isUnseen(0)){
								loadImage();
							}
							else if(node.name2){
								loadImage(true);
							}
						}
						else{
							setTimeout(function(){
								var nameskin1=node.name1;
								var nameskin2=node.name2;
								if(nameskin1&&nameskin1.startsWith('gz_')){
									nameskin1=nameskin1.slice(3);
								}
								if(nameskin2&&nameskin2.startsWith('gz_')){
									nameskin2=nameskin2.slice(3);
								}
								if(!node.isUnseen(0)&&lib.skin[nameskin1]){
									createButtons(lib.skin[nameskin1]);
								}
								if(!node.isUnseen(1)&&lib.skin[nameskin2]){
									createButtons(lib.skin[nameskin2],true);
								}
							});
						}
					}
				}

				uiintro.add(ui.create.div('.placeholder.slim'));
			}
			else if(node.classList.contains('mark')&&node.info&&
				node.parentNode&&node.parentNode.parentNode&&node.parentNode.parentNode.classList.contains('player')){
				var info=node.info;
				var player=node.parentNode.parentNode;
				if(info.name){
					if(typeof info.name=='function'){
						var named=info.name(player.storage[node.skill],player);
						if(named){
							uiintro.add(named);
						}
					}
					else{
						uiintro.add(info.name);
					}
				}
				else if(info.name!==false){
					uiintro.add(get.translation(node.skill));
				}
				if(typeof info.id=='string'&&info.id.startsWith('subplayer')&&
					player.isUnderControl(true)&&player.storage[info.id]&&!_status.video){
					var storage=player.storage[info.id];
					uiintro.addText('当前体力:'+storage.hp+'/'+storage.maxHp);
					if(storage.hs.length){
						uiintro.addText('手牌区');
						uiintro.addSmall(storage.hs);
					}
					if(storage.es.length){
						uiintro.addText('装备区');
						uiintro.addSmall(storage.es);
					}
				}
				if(typeof info.mark=='function'){
					var stint=info.mark(uiintro,player.storage[node.skill],player);
					if(stint){
						var placetext=uiintro.add('<div class="text" style="display:inline">'+stint+'</div>');
						if(!stint.startsWith('<div class="skill"')){
							uiintro._place_text=placetext;
						}
						// if(stint.length<=100){
						// 	uiintro.add('<div class="text center">'+stint+'</div>');
						// }
						// else{
						// 	uiintro.add('<div class="text">'+stint+'</div>');
						// }
					}
				}
				else{
					var stint=get.storageintro(info.content,player.storage[node.skill],player,uiintro,node.skill);
					if(stint){
						if(stint[0]=='@'){
							uiintro.add('<div class="caption">'+stint.slice(1)+'</div>');
						}
						else{
							var placetext=uiintro.add('<div class="text" style="display:inline">'+stint+'</div>');
							if(!stint.startsWith('<div class="skill"')){
								uiintro._place_text=placetext;
							}
						}
						// else if(stint.length<=100){
						// 	uiintro.add('<div class="text center">'+stint+'</div>');
						// }
						// else{
						// 	uiintro.add('<div class="text">'+stint+'</div>');
						// }
					}
				}
				uiintro.add(ui.create.div('.placeholder.slim'));
			}
			else if(node.classList.contains('card')){
				//卡牌长按介绍
				if(ui.arena.classList.contains('observe')&&node.parentNode.classList.contains('handcards')){
					return;
				}
				var name=node.name;
				if(node.parentNode.cardMod){
					var moded=false;
					for(var i in node.parentNode.cardMod){
						var item=node.parentNode.cardMod[i](node);
						if(Array.isArray(item)){
							moded=true;
							uiintro.add(item[0]);
							uiintro._place_text=uiintro.add('<div class="text" style="display:inline">'+item[1]+'</div>');
						}
					}
					if(moded) return uiintro;
				}
				if(node.link&&node.link.name&&lib.card[node.link.name]){
					name=node.link.name;
				}
				if(get.position(node)=='j'&&node.viewAs&&node.viewAs!=name){
					uiintro.add(get.translation(node.viewAs));
					uiintro.add('<div class="text center">('+get.translation(get.translation(node))+')</div>');
					// uiintro.add(get.translation(node.viewAs)+'<br><div class="text center" style="padding-top:5px;">('+get.translation(node)+')</div>');
					uiintro.nosub=true;
					name=node.viewAs;
				}
				else{
					uiintro.add(get.translation(node));
				}
				if(node._banning){
					var clickBanned=function(){
						var banned=lib.config[this.bannedname]||[];
						if(banned.contains(name)){
							banned.remove(name);
						}
						else{
							banned.push(name);
						}
						game.saveConfig(this.bannedname,banned);
						this.classList.toggle('on');
						if(node.updateBanned){
							node.updateBanned();
						}
					};
					var modeorder=lib.config.modeorder||[];
					for(var i in lib.mode){
						modeorder.add(i);
					}
					var list=[];
					uiintro.contentContainer.listen(function(e){
						ui.click.touchpop();
						e.stopPropagation();
					});
					for(var i=0;i<modeorder.length;i++){
						if(node._banning=='online'){
							if(!lib.mode[modeorder[i]].connect) continue;
						}
						else if(modeorder[i]=='connect'||modeorder[i]=='brawl'){
							continue;
						}
						if(lib.config.all.mode.contains(modeorder[i])){
							list.push(modeorder[i]);
						}
					}
					if(lib.card[name]&&lib.card[name].type=='trick') list.push('zhinang_tricks');
					var page=ui.create.div('.menu-buttons.configpopped',uiintro.content);
					var banall=false;
					for(var i=0;i<list.length;i++){
						var cfg=ui.create.div('.config',list[i]=='zhinang_tricks'?'设为智囊':(lib.translate[list[i]]+'模式'),page);
						cfg.classList.add('toggle');
						if(list[i]=='zhinang_tricks'){
							cfg.bannedname=((node._banning=='offline')?'':'connect_')+'zhinang_tricks';
						}
						else if(node._banning=='offline'){
							cfg.bannedname=list[i]+'_bannedcards';
						}
						else{
							cfg.bannedname='connect_'+list[i]+'_bannedcards';
						}
						cfg.listen(clickBanned);
						ui.create.div(ui.create.div(cfg));
						var banned=lib.config[cfg.bannedname]||[];
						if(banned.contains(name)==(list[i]=='zhinang_tricks')){
							cfg.classList.add('on');
							banall=true;
						}
					}
					ui.create.div('.menubutton.pointerdiv',banall?'全部禁用':'全部启用',uiintro.content,function(){
						if(this.innerHTML=='全部禁用'){
							for(var i=0;i<page.childElementCount;i++){
								if(page.childNodes[i].bannedname.indexOf('zhinang_tricks')==-1&&page.childNodes[i].bannedname&&page.childNodes[i].classList.contains('on')){
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML='全部启用';
						}
						else{
							for(var i=0;i<page.childElementCount;i++){
								if(page.childNodes[i].bannedname.indexOf('zhinang_tricks')==-1&&page.childNodes[i].bannedname&&!page.childNodes[i].classList.contains('on')){
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML='全部禁用';
						}
					}).style.marginTop='-10px';
					ui.create.div('.placeholder.slim',uiintro.content);
				}
				else{
					if(lib.translate[name+'_info']){
						if(!uiintro.nosub){
							if(get.subtype(name)=='equip1'){
								var added=false;
								if(lib.card[node.name]&&lib.card[node.name].distance){
									var dist=lib.card[node.name].distance;
									if(dist.attackFrom){
										added=true;
										uiintro.add('<div class="text center">攻击范围:'+(-dist.attackFrom+1)+'</div>');
									}
								}
								if(!added){
									uiintro.add('<div class="text center">攻击范围:1</div>');
								}
							}
							else if(get.subtype(name)){
								uiintro.add('<div class="text center">'+get.translation(get.subtype(name))+'</div>');
							}
							else if(lib.card[name]&&lib.card[name].addinfomenu){
								uiintro.add('<div class="text center">'+lib.card[name].addinfomenu+'</div>');
							}
							else if(lib.card[name]&&lib.card[name].derivation){
								if(typeof lib.card[name].derivation=='string'){
									uiintro.add('<div class="text center">来源:'+get.translation(lib.card[name].derivation)+'</div>');
								}
								else if(lib.card[name].derivationpack){
									uiintro.add('<div class="text center">来源:'+get.translation(lib.card[name].derivationpack+'_card_config')+'包</div>');
								}
							}
							else{
								if(lib.card[name].unique){
									uiintro.add('<div class="text center">特殊'+get.translation(lib.card[name].type)+'牌</div>');
								}
								else{
									if(lib.card[name].type&&lib.translate[lib.card[name].type]) uiintro.add('<div class="text center">'+get.translation(lib.card[name].type)+'牌</div>');
								}
							}
							if(lib.card[name].unique&&lib.card[name].type=='equip'){
								if(lib.cardPile.guozhan&&lib.cardPack.guozhan.contains(name)){
									uiintro.add('<div class="text center">专属装备</div>').style.marginTop='-5px';
								}
								else{
									uiintro.add('<div class="text center">特殊装备</div>').style.marginTop='-5px';
								}
							}
						}
						if(lib.card[name].cardPrompt){
							var str=lib.card[name].cardPrompt(node.link||node),placetext=uiintro.add('<div class="text" style="display:inline">'+str+'</div>');
							if(!str.startsWith('<div class="skill"')){
								uiintro._place_text=placetext;
							}
						}
						else if(lib.translate[name+'_info']){
							var placetext=uiintro.add('<div class="text" style="display:inline">'+lib.translate[name+'_info']+'</div>');
							if(!lib.translate[name+'_info'].startsWith('<div class="skill"')){
								uiintro._place_text=placetext;
							}
						}
						if(get.is.yingbianConditional(node.link||node)){
							const yingbianEffects=get.yingbianEffects(node.link||node);
							if(!yingbianEffects.length){
								const defaultYingbianEffect=get.defaultYingbianEffect(node.link||node);
								if(lib.yingbian.prompt.has(defaultYingbianEffect)) yingbianEffects.push(defaultYingbianEffect);
							}
							if(yingbianEffects.length) uiintro.add(`<div class="text" style="font-family: yuanli">应变:${yingbianEffects.map(value=>lib.yingbian.prompt.get(value)).join(';')}</div>`);
						}
						if(lib.translate[name+'_append']){
							uiintro.add('<div class="text" style="display:inline">'+lib.translate[name+'_append']+'</div>');
						}
					}
					uiintro.add(ui.create.div('.placeholder.slim'));
				}
			}
			else if(node.classList.contains('character')){
				const character=node.link,characterInfo=get.character(node.link);
				let capt=get.translation(character);
				if(characterInfo){
					const infoSex=characterInfo[0];
					if(infoSex&&lib.config.show_sex) capt+=`&nbsp;&nbsp;${infoSex=='none'?'无':lib.translate[infoSex]}`;
					const infoGroup=characterInfo[1];
					if(infoGroup&&lib.config.show_group){
						const group=get.is.double(character,true);
						if(group) capt+=`&nbsp;&nbsp;${group.map(value=>get.translation(value)).join('/')}`;
						else capt+=`&nbsp;&nbsp;${lib.translate[infoGroup]}`;
					}
				}
				uiintro.add(capt);

				if(lib.characterTitle[node.link]){
					uiintro.addText(get.colorspan(lib.characterTitle[node.link]));
				}

				if(node._banning){
					var clickBanned=function(){
						var banned=lib.config[this.bannedname]||[];
						if(banned.contains(character)){
							banned.remove(character);
						}
						else{
							banned.push(character);
						}
						game.saveConfig(this.bannedname,banned);
						this.classList.toggle('on');
						if(node.updateBanned){
							node.updateBanned();
						}
					};
					var modeorder=lib.config.modeorder||[];
					for(var i in lib.mode){
						modeorder.add(i);
					}
					var list=[];
					uiintro.contentContainer.listen(function(e){
						ui.click.touchpop();
						e.stopPropagation();
					});
					for(var i=0;i<modeorder.length;i++){
						if(node._banning=='online'){
							if(!lib.mode[modeorder[i]].connect) continue;
							if(!lib.config['connect_'+modeorder[i]+'_banned']){
								lib.config['connect_'+modeorder[i]+'_banned']=[];
							}
						}
						else if(modeorder[i]=='connect'||modeorder[i]=='brawl'){
							continue;
						}
						if(lib.config.all.mode.contains(modeorder[i])){
							list.push(modeorder[i]);
						}
					}
					var page=ui.create.div('.menu-buttons.configpopped',uiintro.content);
					var banall=false;
					for(var i=0;i<list.length;i++){
						var cfg=ui.create.div('.config',lib.translate[list[i]]+'模式',page);
						cfg.classList.add('toggle');
						if(node._banning=='offline'){
							cfg.bannedname=list[i]+'_banned';
						}
						else{
							cfg.bannedname='connect_'+list[i]+'_banned';
						}
						cfg.listen(clickBanned);
						ui.create.div(ui.create.div(cfg));
						var banned=lib.config[cfg.bannedname]||[];
						if(!banned.contains(character)){
							cfg.classList.add('on');
							banall=true;
						}
					}
					if(node._banning=='offline'){
						var cfg=ui.create.div('.config','随机选将可用',page);
						cfg.classList.add('toggle');
						cfg.listen(function(){
							this.classList.toggle('on');
							if(this.classList.contains('on')){
								lib.config.forbidai_user.remove(character);
							}
							else{
								lib.config.forbidai_user.add(character);
							}
							game.saveConfig('forbidai_user',lib.config.forbidai_user);
						});
						ui.create.div(ui.create.div(cfg));
						if(!lib.config.forbidai_user.contains(character)){
							cfg.classList.add('on');
						}
					}
					ui.create.div('.menubutton.pointerdiv',banall?'全部禁用':'全部启用',uiintro.content,function(){
						if(this.innerHTML=='全部禁用'){
							for(var i=0;i<page.childElementCount;i++){
								if(page.childNodes[i].bannedname&&page.childNodes[i].classList.contains('on')){
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML='全部启用';
						}
						else{
							for(var i=0;i<page.childElementCount;i++){
								if(page.childNodes[i].bannedname&&!page.childNodes[i].classList.contains('on')){
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML='全部禁用';
						}
					}).style.marginTop='-10px';
					ui.create.div('.placeholder.slim',uiintro.content);
				}
				else{
					var infoitem=get.character(character);
					var skills=infoitem[3];
					for(i=0;i<skills.length;i++){
						if(lib.translate[skills[i]+'_info']){
							translation=lib.translate[skills[i]+'_ab']||get.translation(skills[i]).slice(0,2);
							if(lib.skill[skills[i]]&&lib.skill[skills[i]].nobracket){
								uiintro.add('<div><div class="skilln">'+get.translation(skills[i])+'</div><div>'+get.skillInfoTranslation(skills[i])+'</div></div>');
							}
							else{
								uiintro.add('<div><div class="skill">【'+translation+'】</div><div>'+get.skillInfoTranslation(skills[i])+'</div></div>');
							}
							if(lib.translate[skills[i]+'_append']){
								uiintro._place_text=uiintro.add('<div class="text">'+lib.translate[skills[i]+'_append']+'</div>')
							}
						}
					}
					var modepack=lib.characterPack['mode_'+get.mode()];
					if(lib.config.show_favourite&&
					lib.character[node.link]&&(!modepack||!modepack[node.link])&&(!simple||get.is.phoneLayout())){
						var addFavourite=ui.create.div('.text.center.pointerdiv');
						addFavourite.link=node.link;
						addFavourite.style.marginBottom='15px';
						if(lib.config.favouriteCharacter.contains(node.link)){
							addFavourite.innerHTML='移除收藏';
						}
						else{
							addFavourite.innerHTML='添加收藏';
						}
						addFavourite.listen(ui.click.favouriteCharacter)
						uiintro.add(addFavourite);
					}
					else{
						uiintro.add(ui.create.div('.placeholder.slim'));
					}
					var addskin=false;
					if(node.parentNode.classList.contains('menu-buttons')){
						addskin=!lib.config.show_charactercard;
					}
					else{
						addskin=lib.config.change_skin||lib.skin;
					}
					if(addskin&&(!simple||get.is.phoneLayout())){
						var num=1;
						var introadded=false;
						var nameskin=node.link;
						var nameskin2=nameskin;
						var gzbool=false;
						if(nameskin.startsWith('gz_shibing')){
							nameskin=nameskin.slice(3,11);
						}
						else if(nameskin.startsWith('gz_')){
							nameskin=nameskin.slice(3);
							gzbool=true;
						}
						var createButtons=function(num){
							if(!num) return;
							if(!introadded){
								introadded=true;
								uiintro.add('<div class="text center">更改皮肤</div>');
							}
							var buttons=ui.create.div('.buttons.smallzoom.scrollbuttons');
							lib.setMousewheel(buttons);
							for(var i=0;i<=num;i++){
								var button=ui.create.div('.button.character.pointerdiv',buttons,function(){
									if(this._link){
										lib.config.skin[nameskin]=this._link;
										node.style.backgroundImage=this.style.backgroundImage;
										game.saveConfig('skin',lib.config.skin);
									}
									else{
										delete lib.config.skin[nameskin];
										if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) node.setBackground(nameskin2,'character');
										else node.setBackground(nameskin,'character');
										game.saveConfig('skin',lib.config.skin);
									}
								});
								button._link=i;
								if(i){
									button.setBackgroundImage('image/skin/'+nameskin+'/'+i+'.jpg');
								}
								else{
									if(gzbool&&lib.character[nameskin2][4].contains('gzskin')&&lib.config.mode_config.guozhan.guozhanSkin) button.setBackground(nameskin2,'character','noskin');
									else button.setBackground(nameskin,'character','noskin');
								}
							}
							uiintro.add(buttons);
						};
						var loadImage=function(){
							var img=new Image();
							img.onload=function(){
								num++;
								loadImage();
							}
							img.onerror=function(){
								num--;
								createButtons(num);
							}
							img.src=lib.assetURL+'image/skin/'+nameskin+'/'+num+'.jpg';
						}
						if(lib.config.change_skin){
							loadImage();
						}
						else{
							setTimeout(function(){
								createButtons(lib.skin[nameskin]);
							});
						}
					}
				}
			}
			else if(node.classList.contains('equips')&&ui.arena.classList.contains('selecting')){
				(function(){
					uiintro.add('选择装备');
					uiintro.addSmall(Array.from(node.childNodes).filter(node=>!node.classList.contains('feichu')),true);
					uiintro.clickintro=true;
					ui.control.hide();
					uiintro._onclose=function(){
						ui.control.show();
					}
					var confirmbutton;
					for(var i=0;i<uiintro.buttons.length;i++){
						var button=uiintro.buttons[i];
						button.classList.add('pointerdiv');
						if(button.link.classList.contains('selected')){
							button.classList.add('selected');
						}
						button.listen(function(e){
							ui.click.card.call(this.link,'popequip');
							ui.click.window.call(ui.window,e);
							if(this.link.classList.contains('selected')){
								this.classList.add('selected');
							}
							else{
								this.classList.remove('selected');
							}
							if(ui.confirm&&ui.confirm.str&&ui.confirm.str.includes('o')){
								confirmbutton.classList.remove('disabled');
							}
							else{
								confirmbutton.classList.add('disabled');
							}
						});
					}
					var buttoncontainer=uiintro.add(ui.create.div());
					buttoncontainer.style.display='block';
					confirmbutton=ui.create.div('.menubutton.large.pointerdiv','确定',function(){
						if(ui.confirm&&ui.confirm.str&&ui.confirm.str.includes('o')){
							uiintro._clickintro();
							ui.click.ok(ui.confirm.firstChild);
						}
					},buttoncontainer);
					confirmbutton.style.position='relative';
					setTimeout(function(){
						if(ui.confirm&&ui.confirm.str&&ui.confirm.str.includes('o')){
							confirmbutton.classList.remove('disabled');
						}
						else{
							confirmbutton.classList.add('disabled');
						}
					},300);
				}());
			}
			else if(node.classList.contains('identity')&&node.dataset.career){
				var career=node.dataset.career;
				uiintro.add(get.translation(career));
				uiintro.add('<div class="text center" style="padding-bottom:5px">'+lib.translate['_'+career+'_skill_info']+'</div>');
			}
			else if(node.classList.contains('skillbar')){
				if(node==ui.friendBar){
					uiintro.add('友方怒气值');
					uiintro.add('<div class="text center" style="padding-bottom:5px">'+_status.friendRage+'/100</div>');
				}
				else if(node==ui.enemyBar){
					uiintro.add('敌方怒气值');
					uiintro.add('<div class="text center" style="padding-bottom:5px">'+_status.enemyRage+'/100</div>');
				}
			}
			else if(node.parentNode==ui.historybar){
				if(node.dead){
					if(!node.source||node.source==node.player){
						uiintro.add('<div class="text center">'+get.translation(node.player)+'阵亡</div>');
						uiintro.addSmall([node.player]);
					}
					else{
						uiintro.add('<div class="text center">'+get.translation(node.player)+'被'+get.translation(node.source)+'杀害</div>');
						uiintro.addSmall([node.source]);
					}
				}
				if(node.skill){
					uiintro.add('<div class="text center">'+get.translation(node.skill,'skill')+'</div>');
					uiintro._place_text=uiintro.add('<div class="text" style="display:inline">'+get.translation(node.skill,'info')+'</div>');
				}
				if(node.targets&&get.itemtype(node.targets)=='players'){
					uiintro.add('<div class="text center">目标</div>');
					uiintro.addSmall(node.targets);
				}
				if(node.players&&node.players.length>1){
					uiintro.add('<div class="text center">使用者</div>');
					uiintro.addSmall(node.players);
				}
				if(node.cards&&node.cards.length){
					uiintro.add('<div class="text center">卡牌</div>');
					uiintro.addSmall(node.cards);
				}
				for(var i=0;i<node.added.length;i++){
					uiintro.add(node.added[i]);
				}
				if(node.added.length){
					uiintro.add(ui.create.div('.placeholder.slim'));
				}
				if(uiintro.content.firstChild){
					uiintro.content.firstChild.style.paddingTop='3px';
				}
			}
			if(lib.config.touchscreen){
				lib.setScroll(uiintro.contentContainer);
			}
			return uiintro;
		},
		linkintro:function(dialog,content,player){
			dialog.content.firstChild.remove();
			dialog.add('<div class="text center">已横置</div>');
			var list=[];
			for(var i=0;i<game.players.length;i++){
				if(game.players[i].isLinked()&&game.players[i].name&&!game.players[i].name.startsWith('unknown')){
					list.push(game.players[i]);
				}
			}
			if(list.length){
				dialog.add(list,true,true);
			}
		},
		groups:function(){
			return ['wei','shu','wu','qun','jin','western','key'];
		},
		types:function(){
			var types=[];
			for(var i in lib.card){
				if(lib.card[i].mode&&lib.card[i].mode.contains(lib.config.mode)==false) continue;
				if(lib.card[i].forbid&&lib.card[i].forbid.contains(lib.config.mode)) continue;
				if(lib.card[i].type){
					if(lib.card[i].type=='delay') types.add('trick');
					else types.add(lib.card[i].type);
				}
			}
			return types;
		},
		links:function(buttons){
			var links=[];
			for(var i=0;i<buttons.length;i++){
				if(buttons[i].link!=undefined) links.push(buttons[i].link);
			}
			return links;
		},
		threaten:function(target,player,hp){
			var threaten=1;
			var skills=target.getSkills();
			if(!player&&player!==false){
				player=_status.event.player;
			}
			for(var i=0;i<skills.length;i++){
				var info=get.info(skills[i]);
				if(info&&info.ai&&info.ai.threaten){
					if(typeof info.ai.threaten=='function'&&player){
						var tmp=info.ai.threaten(player,target);
						if(typeof tmp=='number'){
							threaten*=tmp;
						}
					}
					else if(typeof info.ai.threaten=='number'){
						threaten*=info.ai.threaten;
					}
				}
			}
			if(hp){
				switch(target.hp){
					case 0:threaten*=1.5;break;
					case 1:threaten*=1.2;break;
				}
				switch(target.countCards('h')){
					case 0:threaten*=1.5;break;
					case 1:threaten*=1.2;break;
				}
			}
			return threaten;
		},
		condition:function(player){
			var num=player.hp;
			if(num>4){
				num=4+Math.sqrt(num-4);
			}
			else{
				if(player.isHealthy()){
					if(player.hp==3){
						num+=0.5;
					}
					else if(player.hp<3){
						num++;
					}
				}
			}
			num+=player.countCards('h')/2;
			var es=player.getCards('e');
			for(var i=0;i<es.length;i++){
				var val=get.equipValueNumber(es[i]);
				if(val>=7) num+=0.8;
				if(val>=5) num+=0.5;
				if(val>=3) num+=0.2;
			}
			return num;
		},
		attitude:function(from,to){
			if(!from||!to) return 0;
			from=from._trueMe||from;
			arguments[0]=from;
			var att=get.rawAttitude.apply(this,arguments);
			if(from.isMad()) att=-att;
			if(to.isMad()&&att>0){
				if(to.identity=='zhu'){
					att=1;
				}
				else{
					att=0;
				}
			}
			if(!_status.tempnofake){
				_status.tempnofake=true;
				if(from.ai.modAttitudeFrom){
					att=from.ai.modAttitudeFrom(from,to,att);
				}
				if(to.ai.modAttitudeTo){
					att=to.ai.modAttitudeTo(from,to,att);
				}
				delete _status.tempnofake;
			}
			return att;
		},
		sgnAttitude:function(){
			return get.sgn(get.attitude.apply(this,arguments));
		},
		useful_raw:function(card,player){
			if(get.position(card)=='j') return -1;
			if(get.position(card)=='e') return get.equipValue(card);
			if(card._modUseful){
				return card._modUseful();
			}
			var i=0;
			if(!player) player=_status.event.player;
			if(player){
				if(_status.event.useCache){
					i = game.callFuncUseStepCache("player.getCardsInUseful",function(player,position,cardname){
						return player.getCards(position,cardname);
					},[player,'h',card.name]).indexOf(card);
				}else{
					i=player.getCards('h',card.name).indexOf(card);
				}
				if(i<0) i=0;
			}
			var aii=get.info(card).ai;
			var useful;
			if(aii&&aii.useful) useful=aii.useful;
			else if(aii&&aii.basic) useful=aii.basic.useful;
			var result;
			if(useful==undefined) result=-1;
			else if(typeof useful=='function'){
				result=useful(card,i);
			}
			else if(typeof useful=='number') result=useful;
			else if(i<useful.length){
				result=useful[i];
			}
			else result=useful[useful.length-1];
			result=game.checkMod(player,card,result,'aiUseful',player);
			return result;
		},
		useful:function(card,player){
			if(_status.event.useCache){
				return game.callFuncUseStepCache("get.useful_raw",get.useful_raw,[card,player]);
			}
			return get.useful_raw(card,player);
		},
		unuseful:function(card){
			return -get.useful(card);
		},
		unuseful2:function(card){
			return 10-get.useful(card);
		},
		unuseful3:function(card){
			if(card.name=='du') return 20;
			return 10-get.useful(card);
		},
		value:function(card,player,method){
			var result=0;
			var value;
			if(Array.isArray(card)){
				if(!card.length) return 0;
				value=0;
				for(var i=0;i<card.length;i++){
					value+=get.value(card[i],player,method);
				}
				return value/Math.sqrt(card.length);
			}
			if(card._modValue){
				return card._modValue(player,method);
			}
			var aii=get.info(card).ai;
			if(aii&&aii.value) value=aii.value;
			else if(aii&&aii.basic) value=aii.basic.value;
			if(player==undefined||get.itemtype(player)!='player') player=_status.event.player;
			var geti=function(){
				var num=0,i;
				var cards=player.getCards('hs',card.name);
				if(cards.contains(card)){
					return cards.indexOf(card);
				}
				return cards.length;
			};
			if(typeof value=='function'){
				result=value(card,player,geti(),method);
			}
			if(typeof value=='number') result=value;
			if(Array.isArray(value)){
				if(method=='raw') result=value[0];
				var num=geti();
				if(num<value.length) result=value[num];
				else result=value[value.length-1];
			}
			result=game.checkMod(player,card,result,'aiValue',player);
			return result;
		},
		equipResult:function(player,target,name){
			var card=get.card();
			if(!card||card.name!=name){
				card={name:name};
			}
			var value1=get.equipValue(card,target);
			var value2=0;
			if(!player.canEquip(card)){
				if(!player.canEquip(card,true)) return 0;
				var current=target.getEquip(card);
				if(current&&current!=card){
					value2=get.equipValue(current,target);
					if(value2>0&&!target.needsToDiscard()&&!get.tag(card,'valueswap')){
						return 0;
					}
				}
			}
			return Math.max(0,value1-value2)/5;
		},
		equipValue:function(card,player){
			if(player==undefined||get.itemtype(player)!='player') player=get.owner(card);
			if(player==undefined||get.itemtype(player)!='player') player=_status.event.player;
			var info=get.info(card);
			if(!info.ai) return 0;
			var value=info.ai.equipValue;
			if(value==undefined){
				if(info.ai.basic&&info.ai.basic.equipValue!=undefined){
					value=info.ai.basic.equipValue;
				}
				else return 0;
			}
			if(typeof value=='number') return value;
			if(typeof value=='function') return value(card,player,null,'raw2');
			return 0;
		},
		equipValueNumber:function(card){
			var info=get.info(card);
			if(info.ai){
				if(typeof info.ai.equipValue=='number') return info.ai.equipValue;
				if(info.ai.basic&&typeof info.ai.basic.equipValue=='number') return info.ai.basic.equipValue;
			}
			return 0;
		},
		disvalue:function(card,player){
			return -get.value(card,player);
		},
		disvalue2:function(card,player){
			return -get.value(card,player,'raw');
		},
		skillthreaten:function(skill,player,target){
			if(!lib.skill[skill]) return 1;
			if(!lib.skill[skill].ai) return 1;
			var threaten=lib.skill[skill].ai.threaten;
			if(typeof threaten=='number') return threaten;
			if(typeof threaten=='function'){
				player=player||_status.event.player;
				target=target||player;
				return threaten(player,target);
			}
			return 1;
		},
		order:function(item){
			var info=get.info(item);
			if(!info) return -1;
			var aii=info.ai;
			var order;
			if(aii&&aii.order) order=aii.order;
			else if(aii&&aii.basic) order=aii.basic.order;
			if(order==undefined) return -1;
			var num=order;
			if(typeof(order)=='function'){
				num=order(item,_status.event.player);
			}
			if(typeof item=='object'&&_status.event.player){
				var player=_status.event.player;
				num=game.checkMod(player,item,num,'aiOrder',player);
			}
			return num;
		},
		result:function(item,skill){
			var result;
			var info=get.info(item);
			if(info.ai) result=get.copy(info.ai.result);
			if(typeof(result)=='function') result=result(item);
			if(!result) result={};
			if(skill){
				var info2=get.info(skill);
				if(info2.ai){
					info2=info2.ai.result;
					for(var i in info2){
						result[i]=info2[i];
					}
				}
			}
			return result;
		},
		effect_use:function(target,card,player,player2,isLink){
			var event=_status.event;
			var eventskill=null;
			if(player==undefined) player=_status.event.player;
			if(typeof card!='string'&&(typeof card!='object'||!card.name)){
				var skillinfo=get.info(event.skill);
				if(event.skill&&skillinfo.viewAs==undefined) card=_status.event.skill;
				else{
					card=get.card();
					if(skillinfo&&skillinfo.viewAs&&card.name===skillinfo.viewAs.name){
						eventskill=event.skill;
					}
				}
			}
			var info=get.info(card);
			if(typeof card=='object'&&info&&info.changeTarget){
				var targets=[target];
				info.changeTarget(player,targets);
				var eff=0;
				for(var i of targets){
					eff+=get.effect(i,card,player,player2,isLink);
				}
				return eff;
			}
			var result=get.result(card,eventskill);
			var result1=result.player_use||result.player,result2=result.target_use||result.target;
			if(typeof result1=='function') result1=result1(player,target,card,isLink);
			if(typeof result2=='function') result2=result2(player,target,card,isLink);
			
			if(typeof result1!='number') result1=0;
			if(typeof result2!='number') result2=0;
			var temp1,temp2,temp3,temp01=0,temp02=0,threaten=1;
			var skills1=player.getSkills().concat(lib.skill.global);
			game.expandSkills(skills1);
			var zerotarget=false,zeroplayer=false;
			for(var i=0;i<skills1.length;i++){
				temp1=get.info(skills1[i]).ai;
				if(temp1&&typeof temp1.effect=='object'&&typeof temp1.effect.player_use=='function'){
					temp1=temp1.effect.player_use(card,player,target,result1,isLink);
				}
				else if(temp1&&typeof temp1.effect=='object'&&typeof temp1.effect.player=='function'){
					temp1=temp1.effect.player(card,player,target,result1,isLink);
				}
				else temp1=undefined;
				if(typeof temp1=='object'){
					if(temp1.length==2||temp1.length==4){
						result1*=temp1[0];
						temp01+=temp1[1];
					}
					if(temp1.length==4){
						result2*=temp1[2];
						temp02+=temp1[3];
					}
				}
				else if(typeof temp1=='number'){
					result1*=temp1;
				}
				else if(temp1=='zeroplayer'){
					zeroplayer=true;
				}
				else if(temp1=='zerotarget'){
					zerotarget=true;
				}
				else if(temp1=='zeroplayertarget'){
					zeroplayer=true;
					zerotarget=true;
				}
			}
			if(target){
				var skills2=target.getSkills().concat(lib.skill.global);
				game.expandSkills(skills2);
				for(var i=0;i<skills2.length;i++){
					temp2=get.info(skills2[i]).ai;
					if(temp2&&temp2.threaten) temp3=temp2.threaten;
					else temp3=undefined;
					if(temp2&&typeof temp2.effect=='function'){
						if(!player.hasSkillTag('ignoreSkill',true,{
							card:card,
							target:target,
							skill:skills2[i],
							isLink:isLink,
						})) temp2=temp2.effect(card,player,target,result2,isLink);
						else temp2=undefined;
					}
					else if(temp2&&typeof temp2.effect=='object'&&typeof temp2.effect.target_use=='function'){
						if(!player.hasSkillTag('ignoreSkill',true,{
							card:card,
							target:target,
							skill:skills2[i],
							isLink:isLink,
						})) temp2=temp2.effect.target_use(card,player,target,result2,isLink);
						else temp2=undefined;
					}
					else if(temp2&&typeof temp2.effect=='object'&&typeof temp2.effect.target=='function'){
						if(!player.hasSkillTag('ignoreSkill',true,{
							card:card,
							target:target,
							skill:skills2[i],
							isLink:isLink,
						})) temp2=temp2.effect.target(card,player,target,result2,isLink);
						else temp2=undefined;
					}
					else temp2=undefined;
					if(typeof temp2=='object'){
						if(temp2.length==2||temp2.length==4){
							result2*=temp2[0];
							temp02+=temp2[1];
						}
						if(temp2.length==4){
							result1*=temp2[2];
							temp01+=temp2[3];
						}
					}
					else if(typeof temp2=='number'){
						result2*=temp2;
					}
					else if(temp2=='zeroplayer'){
						zeroplayer=true;
					}
					else if(temp2=='zerotarget'){
						zerotarget=true;
					}
					else if(temp2=='zeroplayertarget'){
						zeroplayer=true;
						zerotarget=true;
					}
					if(typeof temp3=='function'&&temp3(player,target)!=undefined){
						threaten*=temp3(player,target);
					}
					else if(typeof temp3=='object'){
						if(typeof temp3.target=='number'){
							threaten*=temp3;
						}
						else if(typeof temp3.target=='function'&&temp3(player,target)!=undefined){
							threaten*=temp3(player,target);
						}
					}
					else if(typeof temp3=='number'){
						threaten*=temp3;
					}
				}
				result2+=temp02;
				result1+=temp01;
				if(typeof card=='object'&&!result.ignoreStatus){
					if(get.attitude(player,target)<0){
						result2*=Math.sqrt(threaten);
					}
					else{
						result2*=Math.sqrt(Math.sqrt(threaten));
					}
					if(target.hp==1) result2*=2.5;
					if(target.hp==2) result2*=1.8;
					if(target.countCards('h')==0){
						if(get.tag(card,'respondSha')||get.tag(card,'respondShan')){
							result2*=1.7;
						}
						else{
							result2*=1.5;
						}
					}
					if(target.countCards('h')==1) result2*=1.3;
					if(target.countCards('h')==2) result2*=1.1;
					if(target.countCards('h')>3) result2*=0.5;
					if(target.hp==4) result2*=0.9;
					if(target.hp==5) result2*=0.8;
					if(target.hp>5) result2*=0.6;
				}
			}
			else{
				result2+=temp02;
				result1+=temp01;
			}
			if(zeroplayer) result1=0;
			if(zerotarget) result2=0;
			var final=0;
			if(player2){
				final=(result1*get.attitude(player2,player)+(target?result2*get.attitude(player2,target):0));
			}
			else final=(result1*get.attitude(player,player)+(target?result2*get.attitude(player,target):0));
			if(!isLink&&get.tag(card,'natureDamage')&&!zerotarget){
				var info=get.info(card);
				if(!info||!info.ai||!info.ai.canLink){
					if(target.isLinked()) game.countPlayer(function(current){
						if(current!=target&&current.isLinked()) final+=get.effect(current,card,player,player2,true);
					});
				}
				else if(info.ai.canLink(player,target,card)){
					game.countPlayer(function(current){
						if(current!=target&&current.isLinked()) final+=get.effect(current,card,player,player2,true);
					});
				}
			}
			return final;
		},
		effect:function(target,card,player,player2,isLink){
			var event=_status.event;
			var eventskill=null;
			if(player==undefined) player=_status.event.player;
			if(typeof card!='string'&&(typeof card!='object'||!card.name)){
				var skillinfo=get.info(event.skill);
				if(event.skill&&skillinfo.viewAs==undefined) card=_status.event.skill;
				else{
					card=get.card();
					if(skillinfo&&skillinfo.viewAs&&card.name===skillinfo.viewAs.name){
						eventskill=event.skill;
					}
				}
			}
			var result=get.result(card,eventskill);
			var result1=result.player,result2=result.target;
			if(typeof result1=='function') result1=result1(player,target,card,isLink);
			if(typeof result2=='function') result2=result2(player,target,card,isLink);
			
			if(typeof result1!='number') result1=0;
			if(typeof result2!='number') result2=0;
			var temp1,temp2,temp3,temp01=0,temp02=0,threaten=1;
			var skills1=player.getSkills().concat(lib.skill.global);
			game.expandSkills(skills1);
			var zerotarget=false,zeroplayer=false;
			for(var i=0;i<skills1.length;i++){
				temp1=get.info(skills1[i]).ai;
				if(temp1&&typeof temp1.effect=='object'&&typeof temp1.effect.player=='function'){
					temp1=temp1.effect.player(card,player,target,result1,isLink);
				}
				else temp1=undefined;
				if(typeof temp1=='object'){
					if(temp1.length==2||temp1.length==4){
						result1*=temp1[0];
						temp01+=temp1[1];
					}
					if(temp1.length==4){
						result2*=temp1[2];
						temp02+=temp1[3];
					}
				}
				else if(typeof temp1=='number'){
					result1*=temp1;
				}
				else if(temp1=='zeroplayer'){
					zeroplayer=true;
				}
				else if(temp1=='zerotarget'){
					zerotarget=true;
				}
				else if(temp1=='zeroplayertarget'){
					zeroplayer=true;
					zerotarget=true;
				}
			}
			if(target){
				var skills2=target.getSkills().concat(lib.skill.global);
				game.expandSkills(skills2);
				for(var i=0;i<skills2.length;i++){
					temp2=get.info(skills2[i]).ai;
					if(temp2&&temp2.threaten) temp3=temp2.threaten;
					else temp3=undefined;
					if(temp2&&typeof temp2.effect=='function'){
						if(!player.hasSkillTag('ignoreSkill',true,{
							card:card,
							target:target,
							skill:skills2[i],
							isLink:isLink,
						})) temp2=temp2.effect(card,player,target,result2,isLink);
						else temp2=undefined;
					}
					else if(temp2&&typeof temp2.effect=='object'&&typeof temp2.effect.target=='function'){
						if(!player.hasSkillTag('ignoreSkill',true,{
							card:card,
							target:target,
							skill:skills2[i],
							isLink:isLink,
						})) temp2=temp2.effect.target(card,player,target,result2,isLink);
						else temp2=undefined;
					}
					else temp2=undefined;
					if(typeof temp2=='object'){
						if(temp2.length==2||temp2.length==4){
							result2*=temp2[0];
							temp02+=temp2[1];
						}
						if(temp2.length==4){
							result1*=temp2[2];
							temp01+=temp2[3];
						}
					}
					else if(typeof temp2=='number'){
						result2*=temp2;
					}
					else if(temp2=='zeroplayer'){
						zeroplayer=true;
					}
					else if(temp2=='zerotarget'){
						zerotarget=true;
					}
					else if(temp2=='zeroplayertarget'){
						zeroplayer=true;
						zerotarget=true;
					}
					if(typeof temp3=='function'&&temp3(player,target)!=undefined){
						threaten*=temp3(player,target);
					}
					else if(typeof temp3=='object'){
						if(typeof temp3.target=='number'){
							threaten*=temp3;
						}
						else if(typeof temp3.target=='function'&&temp3(player,target)!=undefined){
							threaten*=temp3(player,target);
						}
					}
					else if(typeof temp3=='number'){
						threaten*=temp3;
					}
				}
				result2+=temp02;
				result1+=temp01;
				if(typeof card=='object'&&!result.ignoreStatus){
						if(get.attitude(player,target)<0){
						result2*=Math.sqrt(threaten);
					}
					else{
						result2*=Math.sqrt(Math.sqrt(threaten));
					}
					// *** continue here ***
					if(target.hp==1) result2*=2.5;
					if(target.hp==2) result2*=1.8;
					if(target.countCards('h')==0){
						if(get.tag(card,'respondSha')||get.tag(card,'respondShan')){
							result2*=1.7;
						}
						else{
							result2*=1.5;
						}
					}
					if(target.countCards('h')==1) result2*=1.3;
					if(target.countCards('h')==2) result2*=1.1;
					if(target.countCards('h')>3) result2*=0.5;
					if(target.hp==4) result2*=0.9;
					if(target.hp==5) result2*=0.8;
					if(target.hp>5) result2*=0.6;
				}
			}
			else{
				result2+=temp02;
				result1+=temp01;
			}
			if(zeroplayer) result1=0;
			if(zerotarget) result2=0;
			var final=0;
			if(player2){
				final=(result1*get.attitude(player2,player)+(target?result2*get.attitude(player2,target):0));
			}
			else final=(result1*get.attitude(player,player)+(target?result2*get.attitude(player,target):0));
			if(!isLink&&get.tag(card,'natureDamage')&&!zerotarget){
				var info=get.info(card);
				if(!info||!info.ai||!info.ai.canLink){
					if(target.isLinked()) game.countPlayer(function(current){
						if(current!=target&&current.isLinked()) final+=get.effect(current,card,player,player2,true);
					});
				}
				else if(info.ai.canLink(player,target,card)){
					game.countPlayer(function(current){
						if(current!=target&&current.isLinked()) final+=get.effect(current,card,player,player2,true);
					});
				}
			}
			return final;
		},
		damageEffect:function(target,player,viewer,nature){
			if(get.itemtype(nature)=='natures'){
				var natures=get.natureList(nature);
				return natures.map(n=>get.damageEffect(target,player,viewer,n)).reduce((p,c)=>p+c,0)/(natures.length||1);
			}
			if(!player){
				player=target;
			}
			if(!viewer){
				viewer=target;
			}
			var name='damage';
			if(nature=='fire'){
				name='firedamage';
			}
			else if(nature=='thunder'){
				name='thunderdamage';
			}
			else if(nature=='ice'){
				name='icedamage';
			}
			var eff=get.effect(target,{name:name},player,viewer);
			if(eff>0&&target.hujia>0) return eff/1.3;
			return eff;
		},
		recoverEffect:function(target,player,viewer){
			if(target.hp==target.maxHp) return 0;
			if(!player){
				player=target;
			}
			if(!viewer){
				viewer=target;
			}
			return get.effect(target,{name:'recover'},player,viewer);
		},
		buttonValue:function(button){
			var card=button.link;
			var player=get.owner(card);
			if(!player) player=_status.event.player;
			if(player.getCards('j').contains(card)){
				var efff=get.effect(player,{
					name:card.viewAs||card.name,
					cards:[card],
				},player,player);
				if(efff>0) return 0.5;
				if(efff==0) return 0;
				return -1.5;
			}
			if(player.getCards('e').contains(card)){
				var evalue=get.value(card,player);
				if(player.hasSkillTag('noe')){
					if(evalue>=7){
						return evalue/6;
					}
					return evalue/10;
				}
				return evalue/3;
			}
			if(player.hasSkillTag('noh')) return 0.1;
			var nh=player.countCards('h');
			switch(nh){
				case 1:return 2;
				case 2:return 1.6;
				case 3:return 1;
				case 4:return 0.8;
				case 5:return 0.6;
				default:return 0.4;
			}
		},
		attitude2:function(to){
			return get.attitude(_status.event.player,to);
		},
	};
	const ai={
		basic:{
			chooseButton:function(check){
				var event=_status.event;
				var i,j,range,buttons,buttons2;
				var ok=false,forced=event.forced;
				var iwhile=100;
				while(iwhile--){
					range=get.select(event.selectButton);
					if(ui.selected.buttons.length>=range[0]){
						ok=true;
					}
					if(range[1]<=-1){
						j=0;
						for(i=0;i<ui.selected.buttons.length;i++){
							j+=check(ui.selected.buttons[i]);
						}
						return (j>0);
					}
					buttons=get.selectableButtons();
					if(buttons.length==0){
						return ok;
					}
					buttons2=buttons.slice(0);
					var ix=0;
					var checkix=check(buttons[0],buttons2);
					for(i=1;i<buttons.length;i++){
						var checkixtmp=check(buttons[i],buttons2);
						if(checkixtmp>checkix){
							ix=i;
							checkix=checkixtmp;
						}
					}
					// buttons.sort(function(a,b){
					// 	return check(b,buttons2)-check(a,buttons2);
					// });
					if(check(buttons[ix])<=0){
						if(!forced||ok){
							return ok;
						}
					}
					buttons[ix].classList.add('selected');
					ui.selected.buttons.add(buttons[ix]);
					game.check();
					if(ui.selected.buttons.length>=range[0]){
						ok=true;
					}
					if(ui.selected.buttons.length==range[1]){
						return true;
					}
				}
			},
			chooseCard:function(check){
				var event=_status.event;
				if(event.filterCard==undefined) return (check()>0);
				var i,j,range,cards,cards2,skills,check,effect;
				var ok=false,forced=event.forced;
				var iwhile=100;
				while(iwhile--){
					range=get.select(event.selectCard);
					if(ui.selected.cards.length>=range[0]){
						ok=true;
					}
					if(range[1]<=-1){
						if(ui.selected.cards.length==0) return true;
						j=0;
						for(i=0;i<ui.selected.cards.length;i++){
							effect=check(ui.selected.cards[i]);
							if(effect<0) j-=Math.sqrt(-effect);
							else j+=Math.sqrt(effect);
						}
						return (j>0);
					}
					cards=get.selectableCards();
					if(!_status.event.player._noSkill){
						cards=cards.concat(get.skills());
					}
					if(cards.length==0){
						return ok;
					}
					cards2=cards.slice(0);
					// cards.sort(function(a,b){
					// 	return (check(b,cards2)-check(a,cards2));
					// });
					var ix=0;
					var checkix=check(cards[0],cards2);
					for(i=1;i<cards.length;i++){
						var checkixtmp=check(cards[i],cards2);
						if(checkixtmp>checkix){
							ix=i;
							checkix=checkixtmp;
						}
					}
					if(check(cards[ix])<=0){
						if(!forced||ok){
							return ok;
						}
					}
					if(typeof cards[ix]=='string'){
						ui.click.skill(cards[ix]);
						var info=get.info(event.skill);
						if(info.filterCard){
							check=info.check||get.unuseful2;
							return (ai.basic.chooseCard(check));
						}
						else{
							return true;
						}
					}
					else{
						cards[ix].classList.add('selected');
						ui.selected.cards.add(cards[ix]);
						game.check();
						if(ui.selected.cards.length>=range[0]){
							ok=true;
						}
						if(ui.selected.cards.length==range[1]){
							return true;
						}
					}
				}
			},
			chooseTarget:function(check){
				var event=_status.event;
				if(event.filterTarget==undefined) return (check()>0);
				var i,j,range,targets,targets2,effect;
				var ok=false,forced=event.forced;
				var iwhile=100;
				while(iwhile--){
					range=get.select(event.selectTarget);
					if(ui.selected.targets.length>=range[0]){
						ok=true;
					}
					if(range[1]<=-1){
						j=0;
						for(i=0;i<ui.selected.targets.length;i++){
							effect=check(ui.selected.targets[i]);
							if(effect<0) j-=Math.sqrt(-effect);
							else j+=Math.sqrt(effect);
						}
						return (j>0);
					}
					else if(range[1]==0){
						return check()>0
					}
					targets=get.selectableTargets();
					if(targets.length==0){
						return range[0]==0||ok;
					}
					targets2=targets.slice(0);
					// targets.sort(function(a,b){
					// 	return check(b)-check(a);
					// });
					var ix=0;
					var checkix=check(targets[0],targets2);
					for(i=1;i<targets.length;i++){
						var checkixtmp=check(targets[i],targets2);
						if(checkixtmp>checkix){
							ix=i;
							checkix=checkixtmp;
						}
					}
					if(check(targets[ix])<=0){
						if(!forced||ok){
							return ok;
						}
					}
					targets[ix].classList.add('selected');
					ui.selected.targets.add(targets[ix]);
					game.check();
					if(ui.selected.targets.length>=range[0]){
						ok=true;
					}
					if(ui.selected.targets.length==range[1]){
						return true;
					}
				}
			}
		},
		get:get
	};
	if('__core-js_shared__' in window) lib.init.init();
	else{
		const coreJSBundle=document.createElement('script');
		coreJSBundle.onerror=coreJSBundle.onload=lib.init.init;
		coreJSBundle.src=`${lib.assetURL}game/core-js-bundle.js`;
		document.head.appendChild(coreJSBundle);
	}
}