diff --git a/game/game.js b/game/game.js index 7da31bb10..feade8156 100644 --- a/game/game.js +++ b/game/game.js @@ -24700,4 +24700,35951 @@ if(nature=='linked') return naturesx.some(n=>lib.linked.includes(n)); return get.is.sameNature(natures,naturesx); }; - if(next. \ No newline at end of file + 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;iparseInt(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;i1) 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;i0||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){ + if(!unlimited&&get.position(card,true)!=='o'&&get.position(card,true)!=='j'){ + game.log('将',card,'移入',this.next,'的判定区失败'); + return; + } + var target=this.next; + var name=card.viewAs||card.name; + var bool=false; + for(var iwhile=0;iwhile<20;iwhile++){ + if(target.canAddJudge(card)){ + bool=true;break; + } + target=target.next; + } + if(!bool){ + game.log(card,'进入了弃牌堆'); + game.cardsDiscard(card); + } + else{ + 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;i1){ + 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'; + } + } + 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'; + } + } + 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.length>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){ + return this.storage[name]=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.contains(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){ + return this.hasStorage(name)?this.getStorage(name):this.setStorage(name,value); + }, + updateStorage:function(name,operation){ + return this.setStorage(name,operation(this.getStorage(name))); + }, + updateStorageAsync:function(name,operation){ + return Promise.resolve(this.getStorage(name)) + .then(value=>operation(value)) + .then(value=>this.setStorage(name,value)) + }, + removeStorage:function(name){ + return player.hasStorage(name)&&delete player.storage[name]; + }, + markSkill:function(name,info,card){ + 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]); + } + game.broadcastAll(function(storage,player,name,info,card){ + if(storage!=undefined){ + 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(); + },this.storage[name],this,name,info,card); + return this; + }, + unmarkSkill:function(name){ + game.addVideo('unmarkSkill',this,name); + 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(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){ + if(typeof target=='object'){ + target=target.name; + } + game.broadcastAll(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 + }); + } + },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;i0; + }, + 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{ + 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(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 (equips.reduce((range,card,index)=>{ + if(index==0) range--; + let newRange=1; + 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-=info.distance.attackFrom; + } + } + return Math.max(range,newRange) + },range)-range); + } + let base=game.checkMod(player,'unchanged','attackRangeBase',player); + if(base!='unchanged'){ + range=base; + } + else{ + const equips=player.getCards('e',function(card){ + return !ui.selected.cards||!ui.selected.cards.contains(card); + }); + range=equips.reduce((range,card,index)=>{ + if(index==0) range--; + let newRange=1; + 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-=info.distance.attackFrom; + } + } + return Math.max(range,newRange); + },1); + } + range=game.checkMod(player,range,'attackRange',player); + return range; + }, + 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=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; + }, + isMaxHp:function(only,raw){ + return game.players.every(value=>{ + if(value.isOut()||value==this) return true; + return only?value.getHp(raw){ + 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'){ + 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'){ + 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'){ + 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;i0){ + 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;i2||!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=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=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=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=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=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;i1){ + if(log!=false&&!_status.video){ + game.log(this,'获得了'+get.cnNumber(card)+'张牌'); + } + if(this.$gainmod){ + this.$gainmod(card); + } + else{ + for(var i=0;i0.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('
'),ui.create.div('.text.textbg',node)); + ui.create.div('','
'+str.split('').join('

')+'
',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(num0){ + 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;gi3){ + 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])+' '+cardnum+''; + } + 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