diff --git a/character/fire.js b/character/fire.js index 027ce4a86..3339b9f0b 100755 --- a/character/fire.js +++ b/character/fire.js @@ -511,7 +511,7 @@ character.fire={ bazhen_info:'当你没装备防具时,始终视为你装备着【八卦阵】。', kanpo_info:'你可以将你的任意一张♠或♣手牌当【无懈可击】使用。', lianhuan_info:'出牌阶段,你可以将你任意一张梅花手牌当【铁索连环】使用或重铸。', - niepan_info:'当你处于濒死状态时,你可以丢弃你所有的牌和你判定区里的牌,并重置你的武将牌,然后摸三张牌且体力回复至3点。', + niepan_info:'限定技,当你处于濒死状态时,你可以丢弃你所有的牌和你判定区里的牌,并重置你的武将牌,然后摸三张牌且体力回复至3点。', quhu_info:'出牌阶段,你可以与一名体力比你多的角色拼电,若你赢,则该角色对其攻击范围内另一名由你指定的角色造成1点伤害。若你没赢,他/她对你造成一点伤害。每回合限用一次。', jieming_info:'你每受到1点伤害,可令任意一名角色将手牌补至其体力上限的张数(不能超过五张)。', qiangxi_info:'出牌阶段,你可以自减一点体力或弃一张武器牌,然后你对你攻击范围内的一名角色造成一点伤害,每回合限一次。', diff --git a/character/yijiang.js b/character/yijiang.js index 088d43b09..0922f337f 100755 --- a/character/yijiang.js +++ b/character/yijiang.js @@ -1803,6 +1803,9 @@ character.yijiang={ filterTarget:function(card,player,target){ return player!=target; }, + filter:function(event,player){ + return player.num('h')>0; + }, filterCard:true, selectCard:-1, discard:false, diff --git a/character/yxs.js b/character/yxs.js index 7a43727b1..aa936f29f 100755 --- a/character/yxs.js +++ b/character/yxs.js @@ -2144,7 +2144,7 @@ character.yxs={ lshengong:'神工', lshengong_info:'出牌阶段限一次,你可以选定场上任意一名角色的装备区的牌,出自己的一张手牌复制该装备,然后可以选择装备上自己或者别的角色的装备区', zhexian:'谪仙', - zhexian_info:'当你处于濒死状态时,你可以丢弃你所有的牌和你判定区里的牌,并重置你的武将牌,然后摸三张牌且体力回复至3点。', + zhexian_info:'限定技,当你处于濒死状态时,你可以丢弃你所有的牌和你判定区里的牌,并重置你的武将牌,然后摸三张牌且体力回复至3点。', miaobi:'妙笔', miaobi_info:'出牌阶段限一次,你可以将一张红桃牌当作五谷丰登使用', cike:'刺客', diff --git a/game/game.js b/game/game.js index 8cf08dd87..90f46723a 100755 --- a/game/game.js +++ b/game/game.js @@ -12,15 +12,16 @@ }, ai:{}, lastdragchange:[], - skillaudio:[ - '界面问题修正', - '引用配音方法调整' - ], + skillaudio:[], dieClose:[] }; var lib={ version:1.74, - changeLog:[], + changeLog:[ + '界面问题修正', + '限制结算速度选项(较卡时建议开启)', + '引用配音方法调整' + ], configprefix:'noname_0.9_', updates:[], canvasUpdates:[], @@ -32,6 +33,7 @@ skilllist:[], characterPack:{}, cardPack:{}, + onresize:[], onDB:function(func){ if(lib.db){ func(); @@ -237,6 +239,10 @@ vvfast:'很快', }, }, + sync_speed:{ + name:'限制结算速度', + init:true + }, right_click:{ name:'右键功能', init:'pause', @@ -1260,6 +1266,19 @@ if(game.changeCoin) game.changeCoin(0); } }, + coin_canvas_playpackconfig:{ + 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'); + } + } + }, update:function(config,map){ for(var i in map){ if(i.indexOf('_playpackconfig')!=-1){ @@ -3377,8 +3396,6 @@ ui.arena.classList.add('thrownhighlight'); game.addVideo('thrownhighlight1'); player.$compare(event.card1,target,event.card2); - // player.$throw(event.card1); - // target.$throw(event.card2); game.log(player,'的拼点牌为',event.card1); game.log(target,'的拼点牌为',event.card2); event.result={ @@ -3953,11 +3970,18 @@ } } player.$throw(cards); + if(lib.config.sync_speed&&cards[0]&&cards[0].clone){ + var waitingForTransition=get.time(); + event.waitingForTransition=waitingForTransition; + cards[0].clone.addEventListener('webkitTransitionEnd',function(){ + if(_status.waitingForTransition==waitingForTransition&&_status.paused){ + game.resume(); + } + delete event.waitingForTransition; + }); + } } event.trigger('useCard'); - // if(event.card.name=='sha'&&lib.config.animation){ - // player.$sha(event.card.nature); - // } if(get.type(card)!='equip'){ var str=''; if(targets.length){ @@ -4045,7 +4069,13 @@ if(event.animate!=false||num>0){ if(num==0){ if(event.delayx!==false){ - game.delayx(); + if(event.waitingForTransition){ + _status.waitingForTransition=event.waitingForTransition; + game.pause(); + } + else{ + game.delayx(); + } } } else game.delayx(0.5); @@ -4112,6 +4142,9 @@ if(info.prepare){ info.prepare(cards,player,targets); } + if(lib.config.low_performance){ + event.discardTransition=true; + } } else{ if(info.lose!=false){ @@ -4122,6 +4155,16 @@ } else if(info.viewAs){ player.$throw(cards); + if(lib.config.sync_speed&&cards[0]&&cards[0].clone){ + var waitingForTransition=get.time(); + event.waitingForTransition=waitingForTransition; + cards[0].clone.addEventListener('webkitTransitionEnd',function(){ + if(_status.waitingForTransition==waitingForTransition&&_status.paused){ + game.resume(); + } + delete event.waitingForTransition; + }); + } } } if((info.line||info.discard!=false)&&targets.length){ @@ -4220,7 +4263,15 @@ } if(num==0){ if(typeof info.delay=='number') game.delay(info.delay); - else if(info.delay!==false&&info.delay!==0) game.delayx(); + 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.background.paused{ filter:blur(3px); -webkit-filter:blur(3px); } -body>.background{z-index:-2} +body>.background{z-index:-5} .popup{padding: 5px;} .removing,.hidden{opacity: 0 !important;} #system>div>div.hidden{opacity:0.5 !important;} @@ -1257,6 +1257,34 @@ div[data-color="unknownm"]{ .browntext{ color: rgb(195,161,223); } +#window>canvas.fun{ + position: absolute; + left: 0; + top: 0; + z-index: -2; + pointer-events: none; +} +#window.canvas_top>canvas.fun{ + z-index: 20; +} +.coin_menu .content>.caption>.coin_buy{ + line-height: 36px; + font-family: 'xinwei'; + font-size: 24px; +} +.coin_menu .content>.caption>.coin_buy>.menubutton{ + width: auto; + display: inline-block; + position: relative; + float: right; + padding-left: 5px; + padding-right: 5px; + height: auto; + font-size: 24px; +} +.coin_menu .content>.caption>.coin_buy>.menubutton.disabled{ + opacity: 0.5; +} .wunature{ font-family:'huangcao','xinwei'; font-size: 24px; diff --git a/mode/versus.js b/mode/versus.js index d22d317e0..c5a03aaf7 100755 --- a/mode/versus.js +++ b/mode/versus.js @@ -785,6 +785,10 @@ mode.versus={ if(lib.storage.single_control&&lib.storage.control_all){ game.onSwapControl(); } + "step 2" + // if(_status.currentPhase==source){ + // source.skip('phase'); + // } } }, versusClickToSwap:function(e){ @@ -1218,7 +1222,6 @@ mode.versus={ } game.replacePlayer(this); } - } } }, diff --git a/play/coin.js b/play/coin.js index 85588bb0d..348634493 100644 --- a/play/coin.js +++ b/play/coin.js @@ -15,17 +15,53 @@ play.coin={ else{ str=''+lib.config.coin+''; } + if(lib.config.coin_canvas_playpackconfig){ + ui.window.classList.add('canvas_top'); + } ui.coin=ui.create.system(str,null,true); - // lib.setPopped(ui.coin,function(){ - // var uiintro=ui.create.dialog('hidden'); - // uiintro.add('商店'); - // uiintro.listen(function(e){ - // e.stopPropagation(); - // }); - // uiintro.add('
本局比赛能否获得胜利?
'); - // uiintro.classList.add('noleave'); - // return uiintro; - // },220,400); + lib.setPopped(ui.coin,function(){ + var uiintro=ui.create.dialog('hidden'); + uiintro.classList.add('coin_menu') + uiintro.add('商店'); + uiintro.listen(function(e){ + e.stopPropagation(); + }); + uiintro.add('
放烟花
'); + var buyfirework=uiintro.content.lastChild.lastChild.lastChild; + if(lib.config.coin<100){ + buyfirework.classList.add('disabled'); + } + if(_status.fireworkbought){ + if(_status.fireworkRunning){ + buyfirework.innerHTML='停止'; + } + else{ + buyfirework.innerHTML='开始'; + } + } + buyfirework.listen(function(){ + if(this.innerHTML=='100金'){ + if(lib.config.coin>=100){ + _status.fireworkbought=true; + game.changeCoin(-100); + game.haveFun.firework(); + } + else{ + return; + } + } + else if(this.innerHTML=='停止'){ + game.haveFun.fireworkStop(); + } + else if(this.innerHTML=='开始'){ + game.haveFun.firework(); + } + ui.click.window(); + }); + + uiintro.classList.add('noleave'); + return uiintro; + },220,400); } }, game:{ @@ -42,6 +78,325 @@ play.coin={ ui.coin.innerHTML=str; } }, + haveFun:{ + fireworkStop:function(){ + _status.fireworkRunning=false; + }, + firework:function(){ + if(_status.fireworkRunning) return; + _status.fireworkRunning=true; + if(game.haveFun.fireworkLoop){ + game.haveFun.fireworkLoop(); + } + else{ + // when animating on canvas, it is best to use requestAnimationFrame instead of setTimeout or setInterval + // not supported in all browsers though and sometimes needs a prefix, so we need a shim + window.requestAnimFrame = ( function() { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function( callback ) { + window.setTimeout( callback, 1000 / 60 ); + }; + })(); + + // now we will setup our basic variables for the demo + var canvas = document.createElement( 'canvas' ), + ctx = canvas.getContext( '2d' ), + // full screen dimensions + cw = ui.window.offsetWidth, + ch = ui.window.offsetHeight, + // firework collection + fireworks = [], + // particle collection + particles = [], + // starting hue + hue = 120, + // when launching fireworks with a click, too many get launched at once without a limiter, one launch per 5 loop ticks + limiterTotal = 5, + limiterTick = 0, + // this will time the auto launches of fireworks, one launch per 80 loop ticks + timerTotal = 80, + timerTick = 0, + mousedown = false, + // mouse x coordinate, + mx, + // mouse y coordinate + my; + + // set canvas dimensions + canvas.width = cw; + canvas.height = ch; + ui.window.appendChild(canvas); + canvas.classList.add('fun'); + lib.onresize.push(function(){ + cw=ui.window.offsetWidth; + ch=ui.window.offsetHeight; + canvas.width = cw; + canvas.height = ch; + }); + + // now we are going to setup our function placeholders for the entire demo + + // get a random number within a range + function random( min, max ) { + return Math.random() * ( max - min ) + min; + } + + // calculate the distance between two points + function calculateDistance( p1x, p1y, p2x, p2y ) { + var xDistance = p1x - p2x, + yDistance = p1y - p2y; + return Math.sqrt( Math.pow( xDistance, 2 ) + Math.pow( yDistance, 2 ) ); + } + + // create firework + function Firework( sx, sy, tx, ty ) { + // actual coordinates + this.x = sx; + this.y = sy; + // starting coordinates + this.sx = sx; + this.sy = sy; + // target coordinates + this.tx = tx; + this.ty = ty; + // distance from starting point to target + this.distanceToTarget = calculateDistance( sx, sy, tx, ty ); + this.distanceTraveled = 0; + // track the past coordinates of each firework to create a trail effect, increase the coordinate count to create more prominent trails + this.coordinates = []; + this.coordinateCount = 3; + // populate initial coordinate collection with the current coordinates + while( this.coordinateCount-- ) { + this.coordinates.push( [ this.x, this.y ] ); + } + this.angle = Math.atan2( ty - sy, tx - sx ); + this.speed = 2; + this.acceleration = 1.05; + this.brightness = random( 50, 70 ); + // circle target indicator radius + this.targetRadius = 1; + } + + // update firework + Firework.prototype.update = function( index ) { + // remove last item in coordinates array + this.coordinates.pop(); + // add current coordinates to the start of the array + this.coordinates.unshift( [ this.x, this.y ] ); + + // cycle the circle target indicator radius + if( this.targetRadius < 8 ) { + this.targetRadius += 0.3; + } else { + this.targetRadius = 1; + } + + // speed up the firework + this.speed *= this.acceleration; + + // get the current velocities based on angle and speed + var vx = Math.cos( this.angle ) * this.speed, + vy = Math.sin( this.angle ) * this.speed; + // how far will the firework have traveled with velocities applied? + this.distanceTraveled = calculateDistance( this.sx, this.sy, this.x + vx, this.y + vy ); + + // if the distance traveled, including velocities, is greater than the initial distance to the target, then the target has been reached + if( this.distanceTraveled >= this.distanceToTarget ) { + createParticles( this.tx, this.ty ); + // remove the firework, use the index passed into the update function to determine which to remove + fireworks.splice( index, 1 ); + } else { + // target not reached, keep traveling + this.x += vx; + this.y += vy; + } + } + + // draw firework + Firework.prototype.draw = function() { + ctx.beginPath(); + // move to the last tracked coordinate in the set, then draw a line to the current x and y + ctx.moveTo( this.coordinates[ this.coordinates.length - 1][ 0 ], this.coordinates[ this.coordinates.length - 1][ 1 ] ); + ctx.lineTo( this.x, this.y ); + ctx.strokeStyle = 'hsl(' + hue + ', 100%, ' + this.brightness + '%)'; + ctx.stroke(); + + ctx.beginPath(); + // draw the target for this firework with a pulsing circle + ctx.arc( this.tx, this.ty, this.targetRadius, 0, Math.PI * 2 ); + ctx.stroke(); + } + + // create particle + function Particle( x, y ) { + this.x = x; + this.y = y; + // track the past coordinates of each particle to create a trail effect, increase the coordinate count to create more prominent trails + this.coordinates = []; + this.coordinateCount = 5; + while( this.coordinateCount-- ) { + this.coordinates.push( [ this.x, this.y ] ); + } + // set a random angle in all possible directions, in radians + this.angle = random( 0, Math.PI * 2 ); + this.speed = random( 1, 10 ); + // friction will slow the particle down + this.friction = 0.95; + // gravity will be applied and pull the particle down + this.gravity = 1; + // set the hue to a random number +-20 of the overall hue variable + this.hue = random( hue - 20, hue + 20 ); + this.brightness = random( 50, 80 ); + this.alpha = 1; + // set how fast the particle fades out + this.decay = random( 0.015, 0.03 ); + } + + // update particle + Particle.prototype.update = function( index ) { + // remove last item in coordinates array + this.coordinates.pop(); + // add current coordinates to the start of the array + this.coordinates.unshift( [ this.x, this.y ] ); + // slow down the particle + this.speed *= this.friction; + // apply velocity + this.x += Math.cos( this.angle ) * this.speed; + this.y += Math.sin( this.angle ) * this.speed + this.gravity; + // fade out the particle + this.alpha -= this.decay; + + // remove the particle once the alpha is low enough, based on the passed in index + if( this.alpha <= this.decay ) { + particles.splice( index, 1 ); + } + } + + // draw particle + Particle.prototype.draw = function() { + ctx. beginPath(); + // move to the last tracked coordinates in the set, then draw a line to the current x and y + ctx.moveTo( this.coordinates[ this.coordinates.length - 1 ][ 0 ], this.coordinates[ this.coordinates.length - 1 ][ 1 ] ); + ctx.lineTo( this.x, this.y ); + ctx.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')'; + ctx.stroke(); + } + + // create particle group/explosion + function createParticles( x, y ) { + // increase the particle count for a bigger explosion, beware of the canvas performance hit with the increased particles though + var particleCount = 30; + while( particleCount-- ) { + particles.push( new Particle( x, y ) ); + } + } + + // main demo loop + function loop() { + // this function will run endlessly with requestAnimationFrame + if(!_status.fireworkRunning){ + canvas.width=cw; + canvas.height=ch; + return; + } + else{ + requestAnimFrame( loop ); + } + + // increase the hue to get different colored fireworks over time + hue += 0.5; + + // normally, clearRect() would be used to clear the canvas + // we want to create a trailing effect though + // setting the composite operation to destination-out will allow us to clear the canvas at a specific opacity, rather than wiping it entirely + ctx.globalCompositeOperation = 'destination-out'; + // decrease the alpha property to create more prominent trails + ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; + ctx.fillRect( 0, 0, cw, ch ); + // change the composite operation back to our main mode + // lighter creates bright highlight points as the fireworks and particles overlap each other + ctx.globalCompositeOperation = 'lighter'; + + // loop over each firework, draw it, update it + var i = fireworks.length; + while( i-- ) { + fireworks[ i ].draw(); + fireworks[ i ].update( i ); + } + + // loop over each particle, draw it, update it + var i = particles.length; + while( i-- ) { + particles[ i ].draw(); + particles[ i ].update( i ); + } + + // launch fireworks automatically to random coordinates, when the mouse isn't down + if( timerTick >= timerTotal ) { + if( !mousedown ) { + // start the firework at the bottom middle of the screen, then set the random target coordinates, the random y coordinates will be set within the range of the top half of the screen + fireworks.push( new Firework( cw / 2, ch, random( 0, cw ), random( 0, ch / 2 ) ) ); + timerTick = 0; + } + } else { + timerTick++; + } + + // limit the rate at which fireworks get launched when mouse is down + if( limiterTick >= limiterTotal ) { + if( mousedown ) { + // start the firework at the bottom middle of the screen, then set the current mouse coordinates as the target + fireworks.push( new Firework( cw / 2, ch, mx, my ) ); + limiterTick = 0; + } + } else { + limiterTick++; + } + } + + + if(lib.config.touchscreen){ + ui.window.addEventListener( 'touchmove', function( e ) { + mx = e.touches[0].clientX - canvas.offsetLeft; + my = e.touches[0].clientY - canvas.offsetTop; + }); + ui.window.addEventListener( 'touchstart', function( e ) { + e.preventDefault(); + mousedown = true; + }); + ui.window.addEventListener( 'touchend', function( e ) { + e.preventDefault(); + mousedown = false; + }); + } + else{ + // mouse event bindings + // update the mouse coordinates on mousemove + ui.window.addEventListener( 'mousemove', function( e ) { + mx = e.pageX - canvas.offsetLeft; + my = e.pageY - canvas.offsetTop; + }); + + // toggle mousedown state and prevent canvas from being selected + ui.window.addEventListener( 'mousedown', function( e ) { + e.preventDefault(); + mousedown = true; + }); + + ui.window.addEventListener( 'mouseup', function( e ) { + e.preventDefault(); + mousedown = false; + }); + } + + // once the window loads, we are ready for some fireworks! + game.haveFun.fireworkLoop=loop; + loop(); + } + } + } }, help:{ '富甲天下':'