diff --git a/index.html b/index.html index e6f6a77b..d7d64c54 100644 --- a/index.html +++ b/index.html @@ -189,7 +189,6 @@ - diff --git a/libs/control.js b/libs/control.js index d61efca7..fee1c45d 100644 --- a/libs/control.js +++ b/libs/control.js @@ -8,7 +8,7 @@ control.js:游戏主要逻辑控制 "use strict"; -function control() { +function control () { this._init(); } @@ -18,6 +18,8 @@ control.prototype._init = function () { this.replayActions = []; this.weathers = {}; this.resizes = []; + this.needUpdate = false; + this.noAutoEvents = true; // --- 注册系统的animationFrame this.registerAnimationFrame("totalTime", false, this._animationFrame_totalTime); this.registerAnimationFrame("autoSave", true, this._animationFrame_autoSave); @@ -27,6 +29,7 @@ control.prototype._init = function () { this.registerAnimationFrame("weather", true, this._animationFrame_weather); this.registerAnimationFrame("tip", true, this._animateFrame_tip); this.registerAnimationFrame("parallelDo", false, this._animationFrame_parallelDo); + this.registerAnimationFrame("updateStatusBar", true, this.updateStatusBar_update); // --- 注册系统的天气 this.registerWeather("rain", this._weather_rain, this._animationFrame_weather_rain); this.registerWeather("snow", this._weather_snow, this._animationFrame_weather_snow); @@ -65,12 +68,12 @@ control.prototype._init = function () { // func:要执行的函数,或插件中的函数名;可接受timestamp(从页面加载完毕到当前所经过的时间)作为参数 control.prototype.registerAnimationFrame = function (name, needPlaying, func) { this.unregisterAnimationFrame(name); - this.renderFrameFuncs.push({name: name, needPlaying: needPlaying, func: func}); + this.renderFrameFuncs.push({ name: name, needPlaying: needPlaying, func: func }); } ////// 注销一个 animationFrame ////// control.prototype.unregisterAnimationFrame = function (name) { - this.renderFrameFuncs = this.renderFrameFuncs.filter(function (x) { return x.name!=name; }); + this.renderFrameFuncs = this.renderFrameFuncs.filter(function (x) { return x.name != name; }); } ////// 设置requestAnimationFrame ////// @@ -86,7 +89,7 @@ control.prototype._setRequestAnimationFrame = function () { } catch (e) { main.log(e); - main.log("ERROR in requestAnimationFrame["+b.name+"]:已自动注销该项。"); + main.log("ERROR in requestAnimationFrame[" + b.name + "]:已自动注销该项。"); core.unregisterAnimationFrame(b.name); } } @@ -97,20 +100,20 @@ control.prototype._setRequestAnimationFrame = function () { } control.prototype._checkRequestAnimationFrame = function () { - (function() { + (function () { var lastTime = 0; var vendors = ['webkit', 'moz']; - for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // Webkit中此取消方法的名字变了 window[vendors[x] + 'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) { - window.requestAnimationFrame = function(callback, element) { + window.requestAnimationFrame = function (callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)); - var id = window.setTimeout(function() { + var id = window.setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; @@ -118,7 +121,7 @@ control.prototype._checkRequestAnimationFrame = function () { }; } if (!window.cancelAnimationFrame) { - window.cancelAnimationFrame = function(id) { + window.cancelAnimationFrame = function (id) { clearTimeout(id); }; } @@ -130,7 +133,7 @@ control.prototype._animationFrame_totalTime = function (timestamp) { core.animateFrame.totalTimeStart = timestamp; if (core.isPlaying()) { core.status.hero.statistics.totalTime = core.animateFrame.totalTime; - core.status.hero.statistics.currTime += timestamp-(core.status.hero.statistics.start||timestamp); + core.status.hero.statistics.currTime += timestamp - (core.status.hero.statistics.start || timestamp); core.status.hero.statistics.start = timestamp; } } @@ -151,8 +154,8 @@ control.prototype._animationFrame_globalAnimate = function (timestamp) { }); // Global floor images - core.maps._drawFloorImages(core.status.floorId, core.canvas.bg, 'bg', core.status.floorAnimateObjs||[], core.status.globalAnimateStatus); - core.maps._drawFloorImages(core.status.floorId, core.canvas.fg, 'fg', core.status.floorAnimateObjs||[], core.status.globalAnimateStatus); + core.maps._drawFloorImages(core.status.floorId, core.canvas.bg, 'bg', core.status.floorAnimateObjs || [], core.status.globalAnimateStatus); + core.maps._drawFloorImages(core.status.floorId, core.canvas.fg, 'fg', core.status.floorAnimateObjs || [], core.status.globalAnimateStatus); // Global Autotile Animate core.status.autotileAnimateObjs.forEach(function (block) { @@ -213,7 +216,7 @@ control.prototype._animationFrame_weather = function (timestamp) { core.doFunc(core.control.weathers[type].frameFunc, core.control, timestamp, core.animateFrame.weather.level); } catch (e) { main.log(e); - main.log("ERROR in weather["+type+"]:已自动注销该项。"); + main.log("ERROR in weather[" + type + "]:已自动注销该项。"); core.unregisterWeather(type); } } @@ -228,7 +231,7 @@ control.prototype._animationFrame_weather_rain = function (timestamp, level) { core.animateFrame.weather.nodes.forEach(function (p) { ctx.beginPath(); - ctx.moveTo(p.x-ox, p.y-oy); + ctx.moveTo(p.x - ox, p.y - oy); ctx.lineTo(p.x + p.l * p.xs - ox, p.y + p.l * p.ys - oy); ctx.stroke(); @@ -261,17 +264,17 @@ control.prototype._animationFrame_weather_snow = function (timestamp, level) { // update p.x += Math.sin(angle) * core.animateFrame.weather.level; p.y += Math.cos(angle + p.d) + 1 + p.r / 2; - if (p.x > core.bigmap.width*32 + 5 || p.x < -5 || p.y > core.bigmap.height*32) { + if (p.x > core.bigmap.width * 32 + 5 || p.x < -5 || p.y > core.bigmap.height * 32) { if (Math.random() > 1 / 3) { - p.x = Math.random() * core.bigmap.width*32; + p.x = Math.random() * core.bigmap.width * 32; p.y = -10; } else { if (Math.sin(angle) > 0) p.x = -5; else - p.x = core.bigmap.width*32 + 5; - p.y = Math.random() * core.bigmap.height*32; + p.x = core.bigmap.width * 32 + 5; + p.y = Math.random() * core.bigmap.height * 32; } } }); @@ -315,7 +318,7 @@ control.prototype.__animateFrame_weather_image = function (timestamp, level) { core.drawImage('weather', image, node.x + i * width, node.y + j * height); } } - core.setAlpha('weather',1); + core.setAlpha('weather', 1); core.animateFrame.weather.time = timestamp; } @@ -374,10 +377,10 @@ control.prototype.showStartAnimate = function (noAnimate, callback) { } control.prototype._showStartAnimate_resetDom = function () { - core.dom.startPanel.style.opacity=1; - core.dom.startPanel.style.display="block"; - core.dom.startTop.style.opacity=1; - core.dom.startTop.style.display="block"; + core.dom.startPanel.style.opacity = 1; + core.dom.startPanel.style.display = "block"; + core.dom.startTop.style.opacity = 1; + core.dom.startTop.style.display = "block"; core.dom.startButtonGroup.style.display = 'none'; core.dom.startButtons.style.display = 'block'; core.dom.levelChooseButtons.style.display = 'none'; @@ -407,12 +410,12 @@ control.prototype.hideStartAnimate = function (callback) { } ////// 游戏是否已经开始 ////// -control.prototype.isPlaying = function() { +control.prototype.isPlaying = function () { return core.status.played; } ////// 清除游戏状态和数据 ////// -control.prototype.clearStatus = function() { +control.prototype.clearStatus = function () { // 停止各个Timeout和Interval for (var i in core.timeout) { clearTimeout(core.timeout[i]); @@ -460,11 +463,11 @@ control.prototype.stopAutomaticRoute = function () { core.status.automaticRoute.destStep = 0; core.status.automaticRoute.movedStep = 0; core.status.automaticRoute.autoStepRoutes = []; - core.status.automaticRoute.destX=null; - core.status.automaticRoute.destY=null; + core.status.automaticRoute.destX = null; + core.status.automaticRoute.destY = null; core.status.automaticRoute.lastDirection = null; core.status.heroStop = true; - if (core.status.automaticRoute.moveStepBeforeStop.length==0) + if (core.status.automaticRoute.moveStepBeforeStop.length == 0) core.deleteCanvas('route'); } @@ -473,7 +476,7 @@ control.prototype.saveAndStopAutomaticRoute = function () { var automaticRoute = core.status.automaticRoute; if (automaticRoute.moveStepBeforeStop.length == 0) { automaticRoute.moveStepBeforeStop = automaticRoute.autoStepRoutes.slice(automaticRoute.autoStep - 1); - if (automaticRoute.moveStepBeforeStop.length>=1) + if (automaticRoute.moveStepBeforeStop.length >= 1) automaticRoute.moveStepBeforeStop[0].step -= automaticRoute.movedStep; } this.stopAutomaticRoute(); @@ -484,7 +487,7 @@ control.prototype.continueAutomaticRoute = function () { // 此函数只应由events.afterOpenDoor和events.afterBattle调用 var moveStep = core.status.automaticRoute.moveStepBeforeStop; //core.status.automaticRoute.moveStepBeforeStop = []; - if(moveStep.length===0 || (moveStep.length===1 && moveStep[0].step===1)) { + if (moveStep.length === 0 || (moveStep.length === 1 && moveStep[0].step === 1)) { core.status.automaticRoute.moveStepBeforeStop = []; } else { @@ -495,7 +498,7 @@ control.prototype.continueAutomaticRoute = function () { ////// 清空剩下的自动寻路列表 ////// control.prototype.clearContinueAutomaticRoute = function (callback) { core.deleteCanvas('route'); - core.status.automaticRoute.moveStepBeforeStop=[]; + core.status.automaticRoute.moveStepBeforeStop = []; if (callback) callback(); } @@ -510,8 +513,8 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) { if (moveStep.length == 0 && (destX != core.status.hero.loc.x || destY != core.status.hero.loc.y || stepPostfix.length == 0)) return; moveStep = moveStep.concat(stepPostfix); - core.status.automaticRoute.destX=destX; - core.status.automaticRoute.destY=destY; + core.status.automaticRoute.destX = destX; + core.status.automaticRoute.destY = destY; this._setAutomaticRoute_drawRoute(moveStep); this._setAutomaticRoute_setAutoSteps(moveStep); // 立刻移动 @@ -520,13 +523,13 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) { control.prototype._setAutomaticRoute_isMoving = function (destX, destY) { if (core.status.automaticRoute.autoHeroMove) { - var lastX = core.status.automaticRoute.destX, lastY=core.status.automaticRoute.destY; + var lastX = core.status.automaticRoute.destX, lastY = core.status.automaticRoute.destY; core.stopAutomaticRoute(); // 双击瞬移 - if (lastX==destX && lastY==destY) { + if (lastX == destX && lastY == destY) { core.status.automaticRoute.moveDirectly = true; setTimeout(function () { - if (core.status.automaticRoute.moveDirectly && core.status.heroMoving==0) { + if (core.status.automaticRoute.moveDirectly && core.status.heroMoving == 0) { core.control.tryMoveDirectly(destX, destY); } core.status.automaticRoute.moveDirectly = false; @@ -538,10 +541,10 @@ control.prototype._setAutomaticRoute_isMoving = function (destX, destY) { } control.prototype._setAutomaticRoute_isTurning = function (destX, destY, stepPostfix) { - if (destX == core.status.hero.loc.x && destY == core.status.hero.loc.y && stepPostfix.length==0) { - if (core.timeout.turnHeroTimeout==null) { + if (destX == core.status.hero.loc.x && destY == core.status.hero.loc.y && stepPostfix.length == 0) { + if (core.timeout.turnHeroTimeout == null) { var routeLength = core.status.route.length; - core.timeout.turnHeroTimeout = setTimeout(function() { + core.timeout.turnHeroTimeout = setTimeout(function () { if (core.status.route.length == routeLength) core.turnHero(); clearTimeout(core.timeout.turnHeroTimeout); core.timeout.turnHeroTimeout = null; @@ -554,14 +557,14 @@ control.prototype._setAutomaticRoute_isTurning = function (destX, destY, stepPos } return true; } - if (core.timeout.turnHeroTimeout!=null) return true; + if (core.timeout.turnHeroTimeout != null) return true; return false; } control.prototype._setAutomaticRoute_clickMoveDirectly = function (destX, destY, stepPostfix) { // 单击瞬间移动 - if (core.status.heroStop && core.status.heroMoving==0) { - if (stepPostfix.length<=1 && !core.hasFlag('__noClickMove__') && core.control.tryMoveDirectly(destX, destY)) + if (core.status.heroStop && core.status.heroMoving == 0) { + if (stepPostfix.length <= 1 && !core.hasFlag('__noClickMove__') && core.control.tryMoveDirectly(destX, destY)) return true; } return false; @@ -576,7 +579,7 @@ control.prototype._setAutomaticRoute_drawRoute = function (moveStep) { }); core.status.automaticRoute.offsetX = sx; core.status.automaticRoute.offsetY = sy; - var ctx = core.createCanvas('route', sx-core.bigmap.offsetX, sy-core.bigmap.offsetY, dx-sx+32, dy-sy+32, 95); + var ctx = core.createCanvas('route', sx - core.bigmap.offsetX, sy - core.bigmap.offsetY, dx - sx + 32, dy - sy + 32, 95); ctx.fillStyle = '#bfbfbf'; ctx.strokeStyle = '#bfbfbf'; ctx.lineWidth = 8; @@ -586,11 +589,11 @@ control.prototype._setAutomaticRoute_drawRoute = function (moveStep) { } else { ctx.beginPath(); - var cx = moveStep[m].x*32 +16 - sx, cy = moveStep[m].y*32+16 - sy; - var currDir = moveStep[m].direction, nextDir = moveStep[m+1].direction; - ctx.moveTo(cx-core.utils.scan[currDir].x*11, cy-core.utils.scan[currDir].y*11); + var cx = moveStep[m].x * 32 + 16 - sx, cy = moveStep[m].y * 32 + 16 - sy; + var currDir = moveStep[m].direction, nextDir = moveStep[m + 1].direction; + ctx.moveTo(cx - core.utils.scan[currDir].x * 11, cy - core.utils.scan[currDir].y * 11); ctx.lineTo(cx, cy); - ctx.lineTo(cx+core.utils.scan[nextDir].x*11, cy+core.utils.scan[nextDir].y*11); + ctx.lineTo(cx + core.utils.scan[nextDir].x * 11, cy + core.utils.scan[nextDir].y * 11); ctx.stroke(); } } @@ -604,19 +607,19 @@ control.prototype._setAutomaticRoute_setAutoSteps = function (moveStep) { if (currStep == null || currStep == dir) step++; else { - core.status.automaticRoute.autoStepRoutes.push({'direction': currStep, 'step': step}); + core.status.automaticRoute.autoStepRoutes.push({ 'direction': currStep, 'step': step }); step = 1; } currStep = dir; }); - core.status.automaticRoute.autoStepRoutes.push({'direction': currStep, 'step': step}); + core.status.automaticRoute.autoStepRoutes.push({ 'direction': currStep, 'step': step }); } ////// 设置勇士的自动行走路线 ////// control.prototype.setAutoHeroMove = function (steps) { - steps=steps||core.status.automaticRoute.autoStepRoutes; + steps = steps || core.status.automaticRoute.autoStepRoutes; if (steps.length == 0) return; - core.status.automaticRoute.autoStepRoutes=steps; + core.status.automaticRoute.autoStepRoutes = steps; core.status.automaticRoute.autoHeroMove = true; core.status.automaticRoute.autoStep = 1; core.status.automaticRoute.destStep = steps[0].step; @@ -631,16 +634,16 @@ control.prototype.setHeroMoveInterval = function (callback) { return; } - core.status.heroMoving=1; + core.status.heroMoving = 1; var toAdd = 1; - if (core.status.replay.speed>3) toAdd = 2; - if (core.status.replay.speed>6) toAdd = 4; - if (core.status.replay.speed>12) toAdd = 8; + if (core.status.replay.speed > 3) toAdd = 2; + if (core.status.replay.speed > 6) toAdd = 4; + if (core.status.replay.speed > 12) toAdd = 8; core.interval.heroMoveInterval = window.setInterval(function () { - core.status.heroMoving+=toAdd; - if (core.status.heroMoving>=8) { + core.status.heroMoving += toAdd; + if (core.status.heroMoving >= 8) { clearInterval(core.interval.heroMoveInterval); core.status.heroMoving = 0; if (callback) callback(); @@ -655,7 +658,7 @@ control.prototype.moveOneStep = function (callback) { ////// 实际每一步的行走过程 ////// control.prototype.moveAction = function (callback) { - if (core.status.heroMoving>0) return; + if (core.status.heroMoving > 0) return; var noPass = core.noPass(core.nextX(), core.nextY()), canMove = core.canMoveHero(); // 下一个点如果不能走 if (noPass || !canMove) return this._moveAction_noPass(canMove, callback); @@ -669,7 +672,7 @@ control.prototype._moveAction_noPass = function (canMove, callback) { if (canMove) core.trigger(core.nextX(), core.nextY()); core.drawHero(); - if (core.status.automaticRoute.moveStepBeforeStop.length==0) { + if (core.status.automaticRoute.moveStepBeforeStop.length == 0) { core.clearContinueAutomaticRoute(); core.stopAutomaticRoute(); } @@ -684,7 +687,7 @@ control.prototype._moveAction_moving = function (callback) { var direction = core.getHeroLoc('direction'); core.control._moveAction_popAutomaticRoute(); core.status.route.push(direction); - + core.moveOneStep(); core.checkRouteFolding(); if (callback) callback(); @@ -715,7 +718,7 @@ control.prototype._moveAction_popAutomaticRoute = function () { ////// 让勇士开始移动 ////// control.prototype.moveHero = function (direction, callback) { // 如果正在移动,直接return - if (core.status.heroMoving!=0) return; + if (core.status.heroMoving != 0) return; if (core.isset(direction)) core.setHeroLoc('direction', direction); @@ -730,7 +733,7 @@ control.prototype._moveHero_moving = function () { var move = function () { if (!core.status.heroStop) { if (core.hasFlag('debug') && core.status.ctrlDown) { - if (core.status.heroMoving!=0) return; + if (core.status.heroMoving != 0) return; // 检测是否穿出去 var nx = core.nextX(), ny = core.nextY(); if (nx < 0 || nx >= core.bigmap.width || ny < 0 || ny >= core.bigmap.height) return; @@ -751,16 +754,16 @@ control.prototype.isMoving = function () { } ////// 停止勇士的一切行动,等待勇士行动结束后,再执行callback ////// -control.prototype.waitHeroToStop = function(callback) { +control.prototype.waitHeroToStop = function (callback) { var lastDirection = core.status.automaticRoute.lastDirection; core.stopAutomaticRoute(); core.clearContinueAutomaticRoute(); if (callback) { - core.status.replay.animate=true; + core.status.replay.animate = true; core.lockControl(); core.status.automaticRoute.moveDirectly = false; - setTimeout(function(){ - core.status.replay.animate=false; + setTimeout(function () { + core.status.replay.animate = false; if (core.isset(lastDirection)) core.setHeroLoc('direction', lastDirection); core.drawHero(); @@ -770,11 +773,11 @@ control.prototype.waitHeroToStop = function(callback) { } ////// 转向 ////// -control.prototype.turnHero = function(direction) { +control.prototype.turnHero = function (direction) { if (direction) { core.setHeroLoc('direction', direction); core.drawHero(); - core.status.route.push("turn:"+direction); + core.status.route.push("turn:" + direction); return; } core.setHeroLoc('direction', core.turnDirection(':right')); @@ -792,16 +795,16 @@ control.prototype.moveDirectly = function (destX, destY, ignoreSteps) { control.prototype.tryMoveDirectly = function (destX, destY) { if (this.nearHero(destX, destY)) return false; var canMoveArray = core.maps.generateMovableArray(); - var dirs = [[destX,destY],[destX-1,destY,"right"],[destX,destY-1,"down"],[destX,destY+1,"up"],[destX+1,destY,"left"]]; + var dirs = [[destX, destY], [destX - 1, destY, "right"], [destX, destY - 1, "down"], [destX, destY + 1, "up"], [destX + 1, destY, "left"]]; var canMoveDirectlyArray = core.canMoveDirectlyArray(dirs, canMoveArray); for (var i = 0; i < dirs.length; ++i) { var d = dirs[i], dx = d[0], dy = d[1], dir = d[2]; - if (dx<0 || dx>=core.bigmap.width|| dy<0 || dy>=core.bigmap.height) continue; - if (dir && !core.inArray(canMoveArray[dx][dy],dir)) continue; - if (canMoveDirectlyArray[i]<0) continue; + if (dx < 0 || dx >= core.bigmap.width || dy < 0 || dy >= core.bigmap.height) continue; + if (dir && !core.inArray(canMoveArray[dx][dy], dir)) continue; + if (canMoveDirectlyArray[i] < 0) continue; if (core.control.moveDirectly(dx, dy, canMoveDirectlyArray[i])) { - if (dir) core.moveHero(dir, function() {}); + if (dir) core.moveHero(dir, function () { }); return true; } } @@ -819,7 +822,7 @@ control.prototype.drawHero = function (status, offset, frame) { var dx = way.x, dy = way.y; var offsetX = typeof offset == 'number' ? dx * offset : (offset.x || 0); var offsetY = typeof offset == 'number' ? dy * offset : (offset.y || 0); - offset = {x: offsetX, y: offsetY, offset: offset}; + offset = { x: offsetX, y: offsetY, offset: offset }; core.clearAutomaticRouteNode(x + dx, y + dy); core.clearMap('hero'); @@ -845,12 +848,12 @@ control.prototype._drawHero_updateViewport = function (x, y, offset) { } control.prototype._drawHero_draw = function (direction, x, y, status, offset, frame) { - offset = offset || {x: 0, y: 0, offset: 0, px: 0, py: 0}; + offset = offset || { x: 0, y: 0, offset: 0, px: 0, py: 0 }; var opacity = core.setAlpha('hero', core.getFlag('__heroOpacity__', 1)) this._drawHero_getDrawObjs(direction, x, y, status, offset).forEach(function (block) { - core.drawImage('hero', block.img, (block.heroIcon[block.status] + (frame || 0))%4*block.width, + core.drawImage('hero', block.img, (block.heroIcon[block.status] + (frame || 0)) % 4 * block.width, block.heroIcon.loc * block.height, block.width, block.height, - block.posx+(32-block.width)/2, block.posy+32-block.height, block.width, block.height); + block.posx + (32 - block.width) / 2, block.posy + 32 - block.height, block.width, block.height); }); core.setAlpha('hero', opacity); } @@ -868,7 +871,7 @@ control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, off "index": index++, }); if (typeof offset.offset == 'number') { - core.status.hero.followers.forEach(function(t) { + core.status.hero.followers.forEach(function (t) { drawObjs.push({ "img": core.material.images.images[t.name], "width": core.material.images.images[t.name].width / 4, @@ -881,8 +884,8 @@ control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, off }); }); } - return drawObjs.sort(function(a, b) { - return a.posy==b.posy?b.index-a.index:a.posy-b.posy; + return drawObjs.sort(function (a, b) { + return a.posy == b.posy ? b.index - a.index : a.posy - b.posy; }); } @@ -894,7 +897,7 @@ control.prototype.setHeroOpacity = function (opacity, moveMode, time, callback) if (callback) callback(); return; } - time /= Math.max(core.status.replay.speed, 1) + time /= Math.max(core.status.replay.speed, 1) var fromOpacity = core.getFlag('__heroOpacity__', 1); var step = 0, steps = parseInt(time / 10); @@ -919,29 +922,29 @@ control.prototype.setHeroOpacity = function (opacity, moveMode, time, callback) // ------ 画布、位置、阻激夹域,显伤 ------ // ////// 设置画布偏移 -control.prototype.setGameCanvasTranslate = function(canvas,x,y){ - var c=core.dom.gameCanvas[canvas]; - x=x*core.domStyle.scale; - y=y*core.domStyle.scale; - c.style.transform='translate('+x+'px,'+y+'px)'; - c.style.webkitTransform='translate('+x+'px,'+y+'px)'; - c.style.OTransform='translate('+x+'px,'+y+'px)'; - c.style.MozTransform='translate('+x+'px,'+y+'px)'; - if(main.mode==='editor' && editor.isMobile){ - c.style.transform='translate('+(x/core.__PIXELS__*96)+'vw,'+(y/core.__PIXELS__*96)+'vw)'; - c.style.webkitTransform='translate('+(x/core.__PIXELS__*96)+'vw,'+(y/core.__PIXELS__*96)+'vw)'; - c.style.OTransform='translate('+(x/core.__PIXELS__*96)+'vw,'+(y/core.__PIXELS__*96)+'vw)'; - c.style.MozTransform='translate('+(x/core.__PIXELS__*96)+'vw,'+(y/core.__PIXELS__*96)+'vw)'; +control.prototype.setGameCanvasTranslate = function (canvas, x, y) { + var c = core.dom.gameCanvas[canvas]; + x = x * core.domStyle.scale; + y = y * core.domStyle.scale; + c.style.transform = 'translate(' + x + 'px,' + y + 'px)'; + c.style.webkitTransform = 'translate(' + x + 'px,' + y + 'px)'; + c.style.OTransform = 'translate(' + x + 'px,' + y + 'px)'; + c.style.MozTransform = 'translate(' + x + 'px,' + y + 'px)'; + if (main.mode === 'editor' && editor.isMobile) { + c.style.transform = 'translate(' + (x / core.__PIXELS__ * 96) + 'vw,' + (y / core.__PIXELS__ * 96) + 'vw)'; + c.style.webkitTransform = 'translate(' + (x / core.__PIXELS__ * 96) + 'vw,' + (y / core.__PIXELS__ * 96) + 'vw)'; + c.style.OTransform = 'translate(' + (x / core.__PIXELS__ * 96) + 'vw,' + (y / core.__PIXELS__ * 96) + 'vw)'; + c.style.MozTransform = 'translate(' + (x / core.__PIXELS__ * 96) + 'vw,' + (y / core.__PIXELS__ * 96) + 'vw)'; } }; ////// 加减画布偏移 control.prototype.addGameCanvasTranslate = function (x, y) { - for(var ii=0,canvas;canvas=core.dom.gameCanvas[ii];ii++){ + for (var ii = 0, canvas; canvas = core.dom.gameCanvas[ii]; ii++) { var id = canvas.getAttribute('id'); - if (id=='ui' || id=='data') continue; // UI层和data层不移动 + if (id == 'ui' || id == 'data') continue; // UI层和data层不移动 var offsetX = x, offsetY = y; - if (core.bigmap.canvas.indexOf(id)>=0) { + if (core.bigmap.canvas.indexOf(id) >= 0) { if (core.bigmap.v2) { offsetX -= (core.bigmap.offsetX - 32 * core.bigmap.posX) + 32; offsetY -= (core.bigmap.offsetY - 32 * core.bigmap.posY) + 32; @@ -955,24 +958,24 @@ control.prototype.addGameCanvasTranslate = function (x, y) { } ////// 更新视野范围 ////// -control.prototype.updateViewport = function() { +control.prototype.updateViewport = function () { // 当前是否应该重绘? if (core.bigmap.v2) { if (core.bigmap.offsetX >= core.bigmap.posX * 32 + 32 || core.bigmap.offsetX <= core.bigmap.posX * 32 - 32 || core.bigmap.offsetY >= core.bigmap.posY * 32 + 32 || core.bigmap.offsetY <= core.bigmap.posY * 32 - 32) { - core.bigmap.posX = parseInt(core.bigmap.offsetX / 32); - core.bigmap.posY = parseInt(core.bigmap.offsetY / 32); - core.redrawMap(); - } + core.bigmap.posX = parseInt(core.bigmap.offsetX / 32); + core.bigmap.posY = parseInt(core.bigmap.offsetY / 32); + core.redrawMap(); + } } else { core.bigmap.posX = core.bigmap.posY = 0; } var offsetX = core.bigmap.v2 ? -(core.bigmap.offsetX - 32 * core.bigmap.posX) - 32 : -core.bigmap.offsetX; var offsetY = core.bigmap.v2 ? -(core.bigmap.offsetY - 32 * core.bigmap.posY) - 32 : -core.bigmap.offsetY; - core.bigmap.canvas.forEach(function(cn){ + core.bigmap.canvas.forEach(function (cn) { core.control.setGameCanvasTranslate(cn, offsetX, offsetY); }); // ------ 路线 @@ -987,7 +990,7 @@ control.prototype.updateViewport = function() { } } } - + } ////// 设置视野范围 ////// @@ -1015,14 +1018,14 @@ control.prototype.moveViewport = function (x, y, moveMode, time, callback) { this.setViewport(32 * x, 32 * y); if (callback) callback(); return; - } + } var px = core.clamp(32 * x, 0, 32 * core.bigmap.width - core.__PIXELS__); var py = core.clamp(32 * y, 0, 32 * core.bigmap.height - core.__PIXELS__); var cx = core.bigmap.offsetX; var cy = core.bigmap.offsetY; var moveFunc = core.applyEasing(moveMode); - var animate=window.setInterval(function() { + var animate = window.setInterval(function () { step++; core.setViewport(cx + moveFunc(step / steps) * (px - cx), cy + moveFunc(step / steps) * (py - cy)); if (step == steps) { @@ -1038,26 +1041,26 @@ control.prototype.moveViewport = function (x, y, moveMode, time, callback) { } ////// 获得勇士面对位置的x坐标 ////// -control.prototype.nextX = function(n) { +control.prototype.nextX = function (n) { if (n == null) n = 1; - return core.getHeroLoc('x')+core.utils.scan[core.getHeroLoc('direction')].x*n; + return core.getHeroLoc('x') + core.utils.scan[core.getHeroLoc('direction')].x * n; } ////// 获得勇士面对位置的y坐标 ////// control.prototype.nextY = function (n) { if (n == null) n = 1; - return core.getHeroLoc('y')+core.utils.scan[core.getHeroLoc('direction')].y*n; + return core.getHeroLoc('y') + core.utils.scan[core.getHeroLoc('direction')].y * n; } ////// 某个点是否在勇士旁边 ////// control.prototype.nearHero = function (x, y, n) { if (n == null) n = 1; - return Math.abs(x-core.getHeroLoc('x'))+Math.abs(y-core.getHeroLoc('y'))<=n; + return Math.abs(x - core.getHeroLoc('x')) + Math.abs(y - core.getHeroLoc('y')) <= n; } ////// 聚集跟随者 ////// control.prototype.gatherFollowers = function () { - var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'), dir=core.getHeroLoc('direction'); + var x = core.getHeroLoc('x'), y = core.getHeroLoc('y'), dir = core.getHeroLoc('direction'); core.status.hero.followers.forEach(function (t) { t.x = x; t.y = y; @@ -1092,7 +1095,7 @@ control.prototype.updateFollowers = function () { ////// 瞬移更新跟随者坐标 ////// control.prototype._moveDirectyFollowers = function (x, y) { var route = core.automaticRoute(x, y); - if (route.length == 0) route = [{x: x, y: y, direction: core.getHeroLoc('direction')}]; + if (route.length == 0) route = [{ x: x, y: y, direction: core.getHeroLoc('direction') }]; var nowx = x, nowy = y; for (var i = 0; i < core.status.hero.followers.length; ++i) { @@ -1115,23 +1118,23 @@ control.prototype._moveDirectyFollowers = function (x, y) { } ////// 更新领域、夹击、阻击的伤害地图 ////// -control.prototype.updateCheckBlock = function(floorId) { +control.prototype.updateCheckBlock = function (floorId) { return this.controldata.updateCheckBlock(floorId); } ////// 检查并执行领域、夹击、阻击事件 ////// control.prototype.checkBlock = function () { - var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'), loc = x+","+y; + var x = core.getHeroLoc('x'), y = core.getHeroLoc('y'), loc = x + "," + y; var damage = core.status.checkBlock.damage[loc]; if (damage) { core.status.hero.hp -= damage; var text = (Object.keys(core.status.checkBlock.type[loc] || {}).join(",")) || "伤害"; - core.drawTip("受到"+text+damage+"点"); + core.drawTip("受到" + text + damage + "点"); core.drawHeroAnimate("zone"); this._checkBlock_disableQuickShop(); core.status.hero.statistics.extraDamage += damage; if (core.status.hero.hp <= 0) { - core.status.hero.hp=0; + core.status.hero.hp = 0; core.updateStatusBar(); core.events.lose(); return; @@ -1157,9 +1160,9 @@ control.prototype._checkBlock_repulse = function (repulse) { if (!repulse || repulse.length == 0) return; var actions = []; repulse.forEach(function (t) { - actions.push({"type": "move", "loc": [t[0],t[1]], "steps": [t[3]], "time": 250, "keep": true, "async": true}); + actions.push({ "type": "move", "loc": [t[0], t[1]], "steps": [t[3]], "time": 250, "keep": true, "async": true }); }); - actions.push({"type": "waitAsync"}); + actions.push({ "type": "waitAsync" }); core.insertAction(actions); } @@ -1169,14 +1172,16 @@ control.prototype._checkBlock_ambush = function (ambush) { // 捕捉效果 var actions = []; ambush.forEach(function (t) { - actions.push({"type": "move", "loc": [t[0],t[1]], "steps": [t[3]], "time": 250, "keep": false, "async":true}); + actions.push({ "type": "move", "loc": [t[0], t[1]], "steps": [t[3]], "time": 250, "keep": false, "async": true }); }); - actions.push({"type": "waitAsync"}); + actions.push({ "type": "waitAsync" }); // 强制战斗 ambush.forEach(function (t) { - actions.push({"type": "function", "function": "function() { "+ - "core.battle('" + t[2] + "', " + t[0]+ "," + t[1] + ", true, core.doAction); "+ - "}", "async": true}); + actions.push({ + "type": "function", "function": "function() { " + + "core.battle('" + t[2] + "', " + t[0] + "," + t[1] + ", true, core.doAction); " + + "}", "async": true + }); }); core.insertAction(actions); } @@ -1219,14 +1224,14 @@ control.prototype._updateDamage_damage = function (floorId, onMap) { if (!block.disable && block.event.cls.indexOf('enemy') == 0 && block.event.displayDamage !== false) { if (core.flags.displayEnemyDamage) { - var damageString = core.enemys.getDamageString(block.event.id, x, y, floorId); - core.status.damage.data.push({text: damageString.damage, px: 32*x+1, py: 32*(y+1)-1, color: damageString.color}); + var damageString = core.enemys.getDamageString(block.event.id, x, y, floorId); + core.status.damage.data.push({ text: damageString.damage, px: 32 * x + 1, py: 32 * (y + 1) - 1, color: damageString.color }); } if (core.flags.displayCritical) { - var critical = core.enemys.nextCriticals(block.event.id, 1, x, y, floorId); - critical = core.formatBigNumber((critical[0]||[])[0], true); - if (critical == '???') critical = '?'; - core.status.damage.data.push({text: critical, px: 32*x+1, py: 32*(y+1)-11, color: '#FFFFFF'}); + var critical = core.enemys.nextCriticals(block.event.id, 1, x, y, floorId); + critical = core.formatBigNumber((critical[0] || [])[0], true); + if (critical == '???') critical = '?'; + core.status.damage.data.push({ text: critical, px: 32 * x + 1, py: 32 * (y + 1) - 11, color: '#FFFFFF' }); } } }); @@ -1235,28 +1240,28 @@ control.prototype._updateDamage_damage = function (floorId, onMap) { control.prototype._updateDamage_extraDamage = function (floorId, onMap) { core.status.damage.extraData = []; if (!core.flags.displayExtraDamage) return; - + var width = core.floors[floorId].width, height = core.floors[floorId].height; var startX = onMap && core.bigmap.v2 ? Math.max(0, core.bigmap.posX - core.bigmap.extend) : 0; var endX = onMap && core.bigmap.v2 ? Math.min(width, core.bigmap.posX + core.__SIZE__ + core.bigmap.extend + 1) : width; var startY = onMap && core.bigmap.v2 ? Math.max(0, core.bigmap.posY - core.bigmap.extend) : 0; var endY = onMap && core.bigmap.v2 ? Math.min(height, core.bigmap.posY + core.__SIZE__ + core.bigmap.extend + 1) : height; - for (var x=startX;x0) { // 该点伤害 + var damage = core.status.checkBlock.damage[x + "," + y] || 0; + if (damage > 0) { // 该点伤害 damage = core.formatBigNumber(damage, true); - core.status.damage.extraData.push({text: damage, px: 32*x+16, py: 32*(y+1)-14, color: '#ffaa33', alpha: alpha}); + core.status.damage.extraData.push({ text: damage, px: 32 * x + 16, py: 32 * (y + 1) - 14, color: '#ffaa33', alpha: alpha }); } else { // 检查捕捉 - if (core.status.checkBlock.ambush[x+","+y]) { - core.status.damage.extraData.push({text: '!', px: 32*x+16, py: 32*(y+1)-14, color: '#ffaa33', alpha: alpha}); + if (core.status.checkBlock.ambush[x + "," + y]) { + core.status.damage.extraData.push({ text: '!', px: 32 * x + 16, py: 32 * (y + 1) - 14, color: '#ffaa33', alpha: alpha }); } } } @@ -1304,9 +1309,9 @@ control.prototype._drawDamage_draw = function (ctx, onMap) { var px = one.px, py = one.py; if (onMap && core.bigmap.v2) { px -= core.bigmap.posX * 32; - py -= core.bigmap.posY * 32; + py -= core.bigmap.posY * 32; if (px < -32 || px > core.__PIXELS__ + 32 || py < -32 || py > core.__PIXELS__ + 32) - return; + return; } var alpha = core.setAlpha(ctx, one.alpha); core.fillBoldText(ctx, one.text, px, py, one.color); @@ -1319,12 +1324,12 @@ control.prototype._drawDamage_draw = function (ctx, onMap) { ////// 选择录像文件 ////// control.prototype.chooseReplayFile = function () { core.readFile(function (obj) { - if (obj.name!=core.firstData.name) return alert("存档和游戏不一致!"); + if (obj.name != core.firstData.name) return alert("存档和游戏不一致!"); if (!obj.route) return alert("无效的录像!"); var _replay = function () { - core.startGame(core.flags.startUsingCanvas?'':obj.hard||'', obj.seed, core.decodeRoute(obj.route)); + core.startGame(core.flags.startUsingCanvas ? '' : obj.hard || '', obj.seed, core.decodeRoute(obj.route)); } - if (obj.version && obj.version!=core.firstData.version) { + if (obj.version && obj.version != core.firstData.version) { core.myconfirm("游戏版本不一致!\n你仍然想播放录像吗?", _replay); return; } @@ -1335,10 +1340,10 @@ control.prototype.chooseReplayFile = function () { ////// 开始播放 ////// control.prototype.startReplay = function (list) { if (!core.isPlaying()) return; - core.status.replay.replaying=true; - core.status.replay.pausing=true; + core.status.replay.replaying = true; + core.status.replay.pausing = true; core.status.replay.failed = false; - core.status.replay.speed=1.0; + core.status.replay.speed = 1.0; core.status.replay.toReplay = core.cloneArray(list); core.status.replay.totalList = core.status.route.concat(list); core.status.replay.steps = 0; @@ -1398,11 +1403,11 @@ control.prototype.speedUpReplay = function () { var speeds = [0.2, 0.5, 1, 2, 3, 6, 12, 24]; for (var i = speeds.length - 2; i >= 0; i--) { if (speeds[i] <= core.status.replay.speed) { - core.status.replay.speed = speeds[i+1]; + core.status.replay.speed = speeds[i + 1]; break; } } - core.drawTip("x"+core.status.replay.speed+"倍"); + core.drawTip("x" + core.status.replay.speed + "倍"); } ////// 减速播放 ////// @@ -1411,18 +1416,18 @@ control.prototype.speedDownReplay = function () { var speeds = [0.2, 0.5, 1, 2, 3, 6, 12, 24]; for (var i = 1; i <= speeds.length; i++) { if (speeds[i] >= core.status.replay.speed) { - core.status.replay.speed = speeds[i-1]; + core.status.replay.speed = speeds[i - 1]; break; } } - core.drawTip("x"+core.status.replay.speed+"倍"); + core.drawTip("x" + core.status.replay.speed + "倍"); } ////// 设置播放速度 ////// control.prototype.setReplaySpeed = function (speed) { if (!core.isPlaying() || !core.isReplaying()) return; core.status.replay.speed = speed; - core.drawTip("x"+core.status.replay.speed+"倍"); + core.drawTip("x" + core.status.replay.speed + "倍"); } ////// 停止播放 ////// @@ -1431,10 +1436,10 @@ control.prototype.stopReplay = function (force) { if (!core.isReplaying() && !force) return; core.status.replay.toReplay = []; core.status.replay.totalList = []; - core.status.replay.replaying=false; - core.status.replay.pausing=false; + core.status.replay.replaying = false; + core.status.replay.pausing = false; core.status.replay.failed = false; - core.status.replay.speed=1.0; + core.status.replay.speed = 1.0; core.status.replay.steps = 0; core.status.replay.save = []; core.deleteCanvas('replay'); @@ -1453,7 +1458,7 @@ control.prototype.rewindReplay = function () { core.playSound('操作失败'); return core.drawTip("请等待当前事件的处理结束"); } - if (core.status.replay.save.length==0) { + if (core.status.replay.save.length == 0) { core.playSound('操作失败'); return core.drawTip("无法再回到上一个节点"); } @@ -1496,11 +1501,11 @@ control.prototype._replay_SL = function () { this._replay_hideProgress(); core.lockControl(); - core.status.event.id='save'; + core.status.event.id = 'save'; var saveIndex = core.saves.saveIndex; - var page=parseInt((saveIndex-1)/5), offset=saveIndex-5*page; + var page = parseInt((saveIndex - 1) / 5), offset = saveIndex - 5 * page; - core.ui._drawSLPanel(10*page+offset); + core.ui._drawSLPanel(10 * page + offset); } ////// 回放时查看怪物手册 ////// @@ -1516,16 +1521,16 @@ control.prototype._replay_book = function () { } if (!core.hasItem('book')) { core.playSound('操作失败'); - return core.drawTip('你没有'+core.material.items['book'].name, 'book'); + return core.drawTip('你没有' + core.material.items['book'].name, 'book'); } this._replay_hideProgress(); // 从“浏览地图”页面打开 - if (core.status.event.id=='viewMaps') + if (core.status.event.id == 'viewMaps') core.status.event.ui = core.status.event.data; core.lockControl(); - core.status.event.id='book'; + core.status.event.id = 'book'; core.useItem('book', true); } @@ -1533,7 +1538,7 @@ control.prototype._replay_book = function () { control.prototype._replay_viewMap = function () { if (!core.isPlaying() || !core.isReplaying()) return; if (!core.status.replay.pausing) { - core.playSound('操作失败'); + core.playSound('操作失败'); return core.drawTip("请先暂停录像"); } if (core.isMoving() || core.status.replay.animate || core.status.event.id) { @@ -1543,7 +1548,7 @@ control.prototype._replay_viewMap = function () { this._replay_hideProgress(); core.lockControl(); - core.status.event.id='viewMaps'; + core.status.event.id = 'viewMaps'; core.ui._drawViewMaps(); } @@ -1560,7 +1565,7 @@ control.prototype._replay_toolbox = function () { this._replay_hideProgress(); core.lockControl(); - core.status.event.id='toolbox'; + core.status.event.id = 'toolbox'; core.ui._drawToolbox(); } @@ -1577,25 +1582,25 @@ control.prototype._replay_equipbox = function () { this._replay_hideProgress(); core.lockControl(); - core.status.event.id='equipbox'; + core.status.event.id = 'equipbox'; core.ui._drawEquipbox(); } ////// 是否正在播放录像 ////// control.prototype.isReplaying = function () { - return (core.status.replay||{}).replaying; + return (core.status.replay || {}).replaying; } ////// 回放 ////// control.prototype.replay = function (force) { if (!core.isPlaying() || !core.isReplaying() - || core.status.replay.animate || core.status.event.id || core.status.replay.failed) return; + || core.status.replay.animate || core.status.event.id || core.status.replay.failed) return; if (core.status.replay.pausing && !force) return; this._replay_drawProgress(); - if (core.status.replay.toReplay.length==0) + if (core.status.replay.toReplay.length == 0) return this._replay_finished(); this._replay_save(); - var action=core.status.replay.toReplay.shift(); + var action = core.status.replay.toReplay.shift(); if (this._doReplayAction(action)) return; this._replay_error(action); } @@ -1607,7 +1612,7 @@ control.prototype.replay = function (force) { // func返回true代表成功处理了此录像行为,false代表没有处理此录像行为。 control.prototype.registerReplayAction = function (name, func) { this.unregisterReplayAction(name); - this.replayActions.push({name: name, func: func}); + this.replayActions.push({ name: name, func: func }); } ////// 注销一个录像行为 ////// @@ -1622,7 +1627,7 @@ control.prototype._doReplayAction = function (action) { if (core.doFunc(this.replayActions[i].func, this, action)) return true; } catch (e) { main.log(e); - main.log("ERROR in replayActions["+this.replayActions[i].name+"]:已自动注销该项。"); + main.log("ERROR in replayActions[" + this.replayActions[i].name + "]:已自动注销该项。"); core.unregisterReplayAction(this.replayActions[i].name); } } @@ -1650,14 +1655,16 @@ control.prototype._replay_finished = function () { control.prototype._replay_save = function () { core.status.replay.steps++; - if (core.status.replay.steps%40==1) { + if (core.status.replay.steps % 40 == 1) { if (core.status.replay.save.length == 30) core.status.replay.save.shift(); - core.status.replay.save.push({"data": core.saveData(), "replay": { - "totalList": core.cloneArray(core.status.replay.totalList), - "toReplay": core.cloneArray(core.status.replay.toReplay), - "steps": core.status.replay.steps - }}); + core.status.replay.save.push({ + "data": core.saveData(), "replay": { + "totalList": core.cloneArray(core.status.replay.totalList), + "toReplay": core.cloneArray(core.status.replay.toReplay), + "steps": core.status.replay.steps + } + }); } } @@ -1701,7 +1708,7 @@ control.prototype._replay_drawProgress = function () { if (!core.dymCanvas.replay) return; if (core.dymCanvas.replay.canvas.style.display == 'none') core.dymCanvas.replay.canvas.style.display = 'block'; var total = core.status.replay.totalList.length, left = total - core.status.replay.toReplay.length; - var content = '播放进度:' + left + ' / ' + total + '('+(left/total*100).toFixed(2)+'%)'; + var content = '播放进度:' + left + ' / ' + total + '(' + (left / total * 100).toFixed(2) + '%)'; var width = 26 + core.calWidth('replay', content, "16px Arial"); core.clearMap('replay'); core.fillRect('replay', 0, 0, width, 40, '#000000'); @@ -1714,31 +1721,31 @@ control.prototype.__replay_getTimeout = function () { } control.prototype._replayAction_move = function (action) { - if (["up","down","left","right"].indexOf(action)<0) return false; + if (["up", "down", "left", "right"].indexOf(action) < 0) return false; core.moveHero(action, core.replay); return true; } control.prototype._replayAction_item = function (action) { - if (action.indexOf("item:")!=0) return false; + if (action.indexOf("item:") != 0) return false; var itemId = action.substring(5); if (!core.canUseItem(itemId)) return false; if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { core.useItem(itemId, false, core.replay); return true; } - var tools = core.getToolboxItems('tools'), + var tools = core.getToolboxItems('tools'), constants = core.getToolboxItems('constants'); - var index, per = core.__SIZE__-1; - if ((index=tools.indexOf(itemId))>=0) { - core.status.event.data = {"toolsPage": Math.floor(index/per)+1, "constantsPage":1}; - index = index%per; + var index, per = core.__SIZE__ - 1; + if ((index = tools.indexOf(itemId)) >= 0) { + core.status.event.data = { "toolsPage": Math.floor(index / per) + 1, "constantsPage": 1 }; + index = index % per; } - else if ((index=constants.indexOf(itemId))>=0) { - core.status.event.data = {"toolsPage": 1, "constantsPage": Math.floor(index/per)+1}; - index = index%per+per; + else if ((index = constants.indexOf(itemId)) >= 0) { + core.status.event.data = { "toolsPage": 1, "constantsPage": Math.floor(index / per) + 1 }; + index = index % per + per; } - if (index<0) return false; + if (index < 0) return false; core.ui._drawToolbox(index); setTimeout(function () { core.ui.closePanel(); @@ -1748,17 +1755,17 @@ control.prototype._replayAction_item = function (action) { } control.prototype._replayAction_equip = function (action) { - if (action.indexOf("equip:")!=0) return false; + if (action.indexOf("equip:") != 0) return false; var equipId = action.substring(6); var ownEquipment = core.getToolboxItems('equips'); - var index = ownEquipment.indexOf(equipId), per = core.__SIZE__-1; - if (index<0) { + var index = ownEquipment.indexOf(equipId), per = core.__SIZE__ - 1; + if (index < 0) { core.removeFlag('__doNotCheckAutoEvents__'); return false; } var cb = function () { - var next = core.status.replay.toReplay[0]||""; + var next = core.status.replay.toReplay[0] || ""; if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { core.removeFlag('__doNotCheckAutoEvents__'); core.checkAutoEvents(); @@ -1772,8 +1779,8 @@ control.prototype._replayAction_equip = function (action) { core.loadEquip(equipId, cb); return true; } - core.status.event.data = {"page":Math.floor(index/per)+1, "selectId":null}; - index = index%per+per; + core.status.event.data = { "page": Math.floor(index / per) + 1, "selectId": null }; + index = index % per + per; core.ui._drawEquipbox(index); setTimeout(function () { core.ui.closePanel(); @@ -1783,7 +1790,7 @@ control.prototype._replayAction_equip = function (action) { } control.prototype._replayAction_unEquip = function (action) { - if (action.indexOf("unEquip:")!=0) return false; + if (action.indexOf("unEquip:") != 0) return false; var equipType = parseInt(action.substring(8)); if (!core.isset(equipType)) { core.removeFlag('__doNotCheckAutoEvents__'); @@ -1791,7 +1798,7 @@ control.prototype._replayAction_unEquip = function (action) { } var cb = function () { - var next = core.status.replay.toReplay[0]||""; + var next = core.status.replay.toReplay[0] || ""; if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { core.removeFlag('__doNotCheckAutoEvents__'); core.checkAutoEvents(); @@ -1814,23 +1821,23 @@ control.prototype._replayAction_unEquip = function (action) { } control.prototype._replayAction_saveEquip = function (action) { - if (action.indexOf('saveEquip:')!=0) return false; + if (action.indexOf('saveEquip:') != 0) return false; core.quickSaveEquip(parseInt(action.substring(10))); core.replay(); return true; } control.prototype._replayAction_loadEquip = function (action) { - if (action.indexOf('loadEquip:')!=0) return false; + if (action.indexOf('loadEquip:') != 0) return false; core.quickLoadEquip(parseInt(action.substring(10))); core.replay(); return true; } control.prototype._replayAction_fly = function (action) { - if (action.indexOf("fly:")!=0) return false; - var floorId=action.substring(4); - var toIndex=core.floorIds.indexOf(floorId); + if (action.indexOf("fly:") != 0) return false; + var floorId = action.substring(4); + var toIndex = core.floorIds.indexOf(floorId); if (!core.canUseItem('fly')) return false; core.ui.drawFly(toIndex); if (core.status.replay.speed == 24) { @@ -1846,7 +1853,7 @@ control.prototype._replayAction_fly = function (action) { } control.prototype._replayAction_shop = function (action) { - if (action.indexOf("shop:")!=0) return false; + if (action.indexOf("shop:") != 0) return false; var shopId = action.substring(5); if (core.canUseQuickShop(shopId) != null || !core.canOpenShop(shopId)) { this._replay_error(shopId); @@ -1873,20 +1880,20 @@ control.prototype._replayAction_getNext = function (action) { } control.prototype._replayAction_moveDirectly = function (action) { - if (action.indexOf("move:")!=0) return false; + if (action.indexOf("move:") != 0) return false; // 忽略连续的瞬移事件;如果大地图某一边超过计算范围则不合并 if (!core.hasFlag('poison') && core.status.thisMap.width < 2 * core.bigmap.extend + core.__SIZE__ && core.status.thisMap.height < 2 * core.bigmap.extend + core.__SIZE__) { - while (core.status.replay.toReplay.length>0 && - core.status.replay.toReplay[0].indexOf('move:')==0) { - core.status.route.push(action); - action = core.status.replay.toReplay.shift(); + while (core.status.replay.toReplay.length > 0 && + core.status.replay.toReplay[0].indexOf('move:') == 0) { + core.status.route.push(action); + action = core.status.replay.toReplay.shift(); } } - var pos=action.substring(5).split(":"); - var x=parseInt(pos[0]), y=parseInt(pos[1]); - var nowx=core.getHeroLoc('x'), nowy=core.getHeroLoc('y'); + var pos = action.substring(5).split(":"); + var x = parseInt(pos[0]), y = parseInt(pos[1]); + var nowx = core.getHeroLoc('x'), nowy = core.getHeroLoc('y'); var ignoreSteps = core.canMoveDirectly(x, y); if (!core.moveDirectly(x, y, ignoreSteps)) return false; if (core.status.replay.speed == 24) { @@ -1894,8 +1901,8 @@ control.prototype._replayAction_moveDirectly = function (action) { return true; } - core.ui.drawArrow('ui', 32*nowx+16-core.bigmap.offsetX, 32*nowy+16-core.bigmap.offsetY, - 32*x+16-core.bigmap.offsetX, 32*y+16-core.bigmap.offsetY, '#FF0000', 3); + core.ui.drawArrow('ui', 32 * nowx + 16 - core.bigmap.offsetX, 32 * nowy + 16 - core.bigmap.offsetY, + 32 * x + 16 - core.bigmap.offsetX, 32 * y + 16 - core.bigmap.offsetY, '#FF0000', 3); var timeout = this.__replay_getTimeout(); if (ignoreSteps < 10) timeout = timeout * ignoreSteps / 10; setTimeout(function () { @@ -1942,10 +1949,10 @@ control.prototype._replayAction_no = function (action) { ////// 自动存档 ////// control.prototype.autosave = function (removeLast) { if (core.hasFlag('__forbidSave__')) return; - var x=null; + var x = null; if (removeLast) { - x=core.status.route.pop(); - core.status.route.push("turn:"+core.getHeroLoc('direction')); + x = core.status.route.pop(); + core.status.route.push("turn:" + core.getHeroLoc('direction')); } if (core.status.event.id == 'action') // 事件中的自动存档 core.setFlag("__events__", core.clone(core.status.event.data)); @@ -1959,7 +1966,7 @@ control.prototype.autosave = function (removeLast) { core.saves.autosave.data.pop(); else { core.saves.autosave.data.shift(); - core.saves.autosave.now=core.saves.autosave.now-1; + core.saves.autosave.now = core.saves.autosave.now - 1; } } core.saves.autosave.updated = true; @@ -1996,8 +2003,8 @@ control.prototype.doSL = function (id, type) { } control.prototype._doSL_save = function (id) { - if (id=='autoSave') { - core.playSound('操作失败'); + if (id == 'autoSave') { + core.playSound('操作失败'); return core.drawTip('不能覆盖自动存档!'); } // 在事件中的存档 @@ -2007,7 +2014,7 @@ control.prototype._doSL_save = function (id) { if (core.isReplaying() && core.status.replay.toReplay.length > 0) { data.__toReplay__ = core.encodeRoute(core.status.replay.toReplay); } - core.setLocalForage("save"+id, data, function() { + core.setLocalForage("save" + id, data, function () { core.saves.saveIndex = id; core.setLocalStorage('saveIndex', core.saves.saveIndex); // 恢复事件 @@ -2015,9 +2022,9 @@ control.prototype._doSL_save = function (id) { core.ui.closePanel(); core.playSound('存档'); core.drawTip('存档成功!'); - }, function(err) { + }, function (err) { main.log(err); - alert("存档失败,错误信息:\n"+err); + alert("存档失败,错误信息:\n" + err); }); core.removeFlag("__events__"); return; @@ -2038,7 +2045,7 @@ control.prototype._doSL_load = function (id, callback) { callback(id, data); } else { - core.getLocalForage(id=='autoSave'?id:"save"+id, null, function(data) { + core.getLocalForage(id == 'autoSave' ? id : "save" + id, null, function (data) { if (id == 'autoSave' && data != null) { core.saves.autosave.data = data; if (!(core.saves.autosave.data instanceof Array)) { @@ -2048,7 +2055,7 @@ control.prototype._doSL_load = function (id, callback) { return core.control._doSL_load(id, callback); } callback(id, data); - }, function(err) { + }, function (err) { main.log(err); alert("无效的存档"); }) @@ -2079,11 +2086,11 @@ control.prototype._doSL_load_afterGet = function (id, data) { return; } core.ui.closePanel(); - core.loadData(data, function() { + core.loadData(data, function () { core.removeFlag('__fromLoad__'); core.drawTip("读档成功"); - if (id!="autoSave") { - core.saves.saveIndex=id; + if (id != "autoSave") { + core.saves.saveIndex = id; core.setLocalStorage('saveIndex', core.saves.saveIndex); } }); @@ -2093,7 +2100,7 @@ control.prototype._doSL_replayLoad_afterGet = function (id, data) { if (!data) { core.playSound('操作失败'); return core.drawTip("无效的存档"); - } + } if (data.version != core.firstData.version) { core.playSound('操作失败'); return core.drawTip("存档版本不匹配"); @@ -2174,16 +2181,16 @@ control.prototype._syncSave_http = function (type, saves) { core.http("POST", "/games/sync.php", formData, function (data) { var response = JSON.parse(data); - if (response.code<0) { - core.drawText("出错啦!\n无法同步存档到服务器。\n错误原因:"+response.msg); + if (response.code < 0) { + core.drawText("出错啦!\n无法同步存档到服务器。\n错误原因:" + response.msg); } else { - core.drawText((type=='all'?"所有存档":"存档"+core.saves.saveIndex)+"同步成功!\n\n您的存档编号+密码: \r[yellow]" - +response.code+response.msg - +"\r\n\n请牢记以上信息(如截图等),在从服务器\n同步存档时使用。\n\r[yellow]另外请注意,存档同步只会保存一个月的时间。\r") + core.drawText((type == 'all' ? "所有存档" : "存档" + core.saves.saveIndex) + "同步成功!\n\n您的存档编号+密码: \r[yellow]" + + response.code + response.msg + + "\r\n\n请牢记以上信息(如截图等),在从服务器\n同步存档时使用。\n\r[yellow]另外请注意,存档同步只会保存一个月的时间。\r") } }, function (e) { - core.drawText("出错啦!\n无法同步存档到服务器。\n错误原因:"+e); + core.drawText("出错啦!\n无法同步存档到服务器。\n错误原因:" + e); }) } @@ -2217,11 +2224,11 @@ control.prototype._syncLoad_http = function (id, password) { var msg = null; try { msg = JSON.parse(LZString.decompressFromBase64(response.msg)); - } catch (e) {} + } catch (e) { } if (!msg) { try { msg = JSON.parse(response.msg); - } catch (e) {} + } catch (e) { } } if (msg) { core.control._syncLoad_write(msg); @@ -2230,40 +2237,40 @@ control.prototype._syncLoad_http = function (id, password) { } } else { - core.drawText("出错啦!\n无法从服务器同步存档。\n错误原因:"+response.msg); + core.drawText("出错啦!\n无法从服务器同步存档。\n错误原因:" + response.msg); } }, function (e) { - core.drawText("出错啦!\n无法从服务器同步存档。\n错误原因:"+e); + core.drawText("出错啦!\n无法从服务器同步存档。\n错误原因:" + e); }); } control.prototype._syncLoad_write = function (data) { if (data instanceof Array) { - core.status.event.selection=1; + core.status.event.selection = 1; core.ui.drawConfirmBox("所有本地存档都将被覆盖,确认?", function () { - for (var i=1;i<=5*(main.savePages||30);i++) { - if (i<=data.length) - core.setLocalForage("save"+i, data[i-1]); + for (var i = 1; i <= 5 * (main.savePages || 30); i++) { + if (i <= data.length) + core.setLocalForage("save" + i, data[i - 1]); else if (core.saves.ids[i]) - core.removeLocalForage("save"+i); + core.removeLocalForage("save" + i); } core.ui.closePanel(); core.drawText("同步成功!\n你的本地所有存档均已被覆盖。"); }, function () { - core.status.event.selection=0; + core.status.event.selection = 0; core.ui._drawSyncSave(); }); } else { // 只覆盖单存档 - core.setLocalForage("save"+core.saves.saveIndex, data, function() { - core.drawText("同步成功!\n单存档已覆盖至存档"+core.saves.saveIndex); + core.setLocalForage("save" + core.saves.saveIndex, data, function () { + core.drawText("同步成功!\n单存档已覆盖至存档" + core.saves.saveIndex); }); } } ////// 存档到本地 ////// -control.prototype.saveData = function() { +control.prototype.saveData = function () { return this.controldata.saveData(); } @@ -2278,7 +2285,7 @@ control.prototype.getSave = function (index, callback) { if (core.saves.autosave.data != null) callback(core.saves.autosave.data); else { - core.getLocalForage("autoSave", null, function(data) { + core.getLocalForage("autoSave", null, function (data) { if (data != null) { core.saves.autosave.data = data; if (!(core.saves.autosave.data instanceof Array)) { @@ -2287,16 +2294,16 @@ control.prototype.getSave = function (index, callback) { core.saves.autosave.now = core.saves.autosave.data.length; } callback(core.saves.autosave.data); - }, function(err) { + }, function (err) { main.log(err); callback(null); }); } return; } - core.getLocalForage("save"+index, null, function(data) { + core.getLocalForage("save" + index, null, function (data) { if (callback) callback(data); - }, function(err) { + }, function (err) { main.log(err); if (callback) callback(null); }); @@ -2317,8 +2324,8 @@ control.prototype.getSaves = function (ids, callback) { } control.prototype.getAllSaves = function (callback) { - var ids = Object.keys(core.saves.ids).filter(function(x){return x!=0;}) - .sort(function(a,b) {return a-b;}), saves = []; + var ids = Object.keys(core.saves.ids).filter(function (x) { return x != 0; }) + .sort(function (a, b) { return a - b; }), saves = []; this.getSaves(ids, function (data) { for (var i = 0; i < ids.length; ++i) { if (data[i] != null) @@ -2332,21 +2339,21 @@ control.prototype.getAllSaves = function (callback) { control.prototype.getSaveIndexes = function (callback) { var indexes = {}; core.keysLocalForage(function (err, keys) { - if (err) { - main.log(err); - return callback(indexes); - } - keys.forEach(function (key) { + if (err) { + main.log(err); + return callback(indexes); + } + keys.forEach(function (key) { core.control._getSaveIndexes_getIndex(indexes, key); - }); - callback(indexes); - }); + }); + callback(indexes); + }); } control.prototype._getSaveIndexes_getIndex = function (indexes, name) { - var e = new RegExp('^'+core.firstData.name+"_(save\\d+|autoSave)$").exec(name); + var e = new RegExp('^' + core.firstData.name + "_(save\\d+|autoSave)$").exec(name); if (e) { - if (e[1]=='autoSave') indexes[0]=true; + if (e[1] == 'autoSave') indexes[0] = true; else indexes[parseInt(e[1].substring(4))] = true; } } @@ -2467,7 +2474,7 @@ control.prototype.getStatusLabel = function (name) { control.prototype.setBuff = function (name, value) { // 仅保留三位有效buff值 value = parseFloat(value.toFixed(3)); - this.setFlag('__'+name+'_buff__', value); + this.setFlag('__' + name + '_buff__', value); } ////// 加减某个属性的增幅值 ////// @@ -2475,12 +2482,12 @@ control.prototype.addBuff = function (name, value) { var buff = this.getBuff(name) + value; // 仅保留三位有效buff值 buff = parseFloat(buff.toFixed(3)); - this.setFlag('__'+name+'_buff__', buff); + this.setFlag('__' + name + '_buff__', buff); } ////// 获得某个属性的增幅值 ////// control.prototype.getBuff = function (name) { - return core.getFlag('__'+name+'_buff__', 1); + return core.getFlag('__' + name + '_buff__', 1); } ////// 获得或移除毒衰咒效果 ////// @@ -2492,7 +2499,7 @@ control.prototype.triggerDebuff = function (action, type) { control.prototype.setHeroLoc = function (name, value, noGather) { if (!core.status.hero) return; core.status.hero.loc[name] = value; - if ((name=='x' || name=='y') && !noGather) { + if ((name == 'x' || name == 'y') && !noGather) { this.gatherFollowers(); } } @@ -2512,7 +2519,7 @@ control.prototype.getHeroLoc = function (name) { control.prototype.getLvName = function (lv) { if (!core.status.hero) return null; if (lv == null) lv = core.status.hero.lv; - return ((core.firstData.levelUp||[])[lv-1]||{}).title || lv; + return ((core.firstData.levelUp || [])[lv - 1] || {}).title || lv; } ////// 获得下个等级所需经验;如果不存在下个等级,返回null。 ////// @@ -2526,32 +2533,32 @@ control.prototype.getNextLvUpNeed = function () { } ////// 设置某个自定义变量或flag ////// -control.prototype.setFlag = function(name, value) { +control.prototype.setFlag = function (name, value) { if (value == null) return this.removeFlag(name); if (!core.status.hero) return; - core.status.hero.flags[name]=value; + core.status.hero.flags[name] = value; } ////// 增加某个flag数值 ////// -control.prototype.addFlag = function(name, value) { +control.prototype.addFlag = function (name, value) { if (!core.status.hero) return; core.setFlag(name, core.getFlag(name, 0) + value); } ////// 获得某个自定义变量或flag ////// -control.prototype.getFlag = function(name, defaultValue) { +control.prototype.getFlag = function (name, defaultValue) { if (!core.status.hero) return defaultValue; var value = core.status.hero.flags[name]; return value != null ? value : defaultValue; } ////// 是否存在某个自定义变量或flag,且值为true ////// -control.prototype.hasFlag = function(name) { +control.prototype.hasFlag = function (name) { return !!core.getFlag(name); } ////// 删除某个自定义变量或flag ////// -control.prototype.removeFlag = function(name) { +control.prototype.removeFlag = function (name) { if (!core.status.hero) return; delete core.status.hero.flags[name]; } @@ -2597,7 +2604,7 @@ control.prototype.unlockControl = function () { } ////// 开启debug模式 ////// -control.prototype.debug = function() { +control.prototype.debug = function () { core.setFlag('debug', true); core.drawText("\t[调试模式开启]此模式下按住Ctrl键(或Ctrl+Shift键)可以穿墙并忽略一切事件。\n此模式下将无法上传成绩。"); } @@ -2626,7 +2633,7 @@ control.prototype.checkRouteFolding = function () { var hero = core.clone(core.status.hero, function (name, value) { return name != 'steps' && typeof value == 'number'; }); - var index = [core.getHeroLoc('x'),core.getHeroLoc('y'),core.getHeroLoc('direction').charAt(0)].join(','); + var index = [core.getHeroLoc('x'), core.getHeroLoc('y'), core.getHeroLoc('direction').charAt(0)].join(','); core.status.routeFolding = core.status.routeFolding || {}; if (core.status.routeFolding[index]) { var one = core.status.routeFolding[index]; @@ -2638,7 +2645,7 @@ control.prototype.checkRouteFolding = function () { this._bindRoutePush(); } } - core.status.routeFolding[index] = {hero: hero, length: core.status.route.length}; + core.status.routeFolding[index] = { hero: hero, length: core.status.route.length }; } // ------ 天气,色调,BGM ------ // @@ -2659,7 +2666,7 @@ control.prototype.setWeather = function (type, level) { if (level == null) level = core.animateFrame.weather.level; level = core.clamp(parseInt(level) || 5, 1, 10); // 当前天气:则忽略 - if (type==core.animateFrame.weather.type && level == core.animateFrame.weather.level) return; + if (type == core.animateFrame.weather.type && level == core.animateFrame.weather.level) return; // 计算当前的宽高 core.createCanvas('weather', 0, 0, core.__PIXELS__, core.__PIXELS__, 80); @@ -2671,7 +2678,7 @@ control.prototype.setWeather = function (type, level) { core.doFunc(this.weathers[type].initFunc, this, level); } catch (e) { main.log(e); - main.log("ERROR in weather["+type+"]:已自动注销该项。"); + main.log("ERROR in weather[" + type + "]:已自动注销该项。"); core.unregisterWeather(type); } } @@ -2694,11 +2701,11 @@ control.prototype.unregisterWeather = function (name) { } control.prototype._weather_rain = function (level) { - var number = level * parseInt(20*core.bigmap.width*core.bigmap.height/(core.__SIZE__*core.__SIZE__)); - for (var a=0;a 1) core.screenFlash(color, time * 3, times - 1, moveMode, callback); else { @@ -2826,7 +2833,7 @@ control.prototype.screenFlash = function (color, time, times, moveMode, callback ////// 播放背景音乐 ////// control.prototype.playBgm = function (bgm, startTime) { bgm = core.getMappedName(bgm); - if (main.mode!='play' || !core.material.bgms[bgm]) return; + if (main.mode != 'play' || !core.material.bgms[bgm]) return; // 如果不允许播放 if (!core.musicStatus.bgmStatus) { try { @@ -2845,7 +2852,7 @@ control.prototype.playBgm = function (bgm, startTime) { this._playBgm_play(bgm, startTime); } catch (e) { - console.log("无法播放BGM "+bgm); + console.log("无法播放BGM " + bgm); main.log(e); core.musicStatus.playingBgm = null; } @@ -2874,7 +2881,7 @@ control.prototype._playBgm_play = function (bgm, startTime) { ///// 设置当前背景音乐的播放速度 ////// control.prototype.setBgmSpeed = function (speed, usePitch) { var bgm = core.musicStatus.playingBgm; - if (main.mode!='play' || !core.material.bgms[bgm]) return; + if (main.mode != 'play' || !core.material.bgms[bgm]) return; bgm = core.material.bgms[bgm]; if (speed < 30 || speed > 300) return; bgm.playbackRate = speed / 100; @@ -2882,7 +2889,7 @@ control.prototype.setBgmSpeed = function (speed, usePitch) { if (bgm.preservesPitch != null) { if (bgm.__preservesPitch == null) bgm.__preservesPitch = bgm.preservesPitch; - if (usePitch == null) bgm.preservesPitch = bgm.__preservesPitch; + if (usePitch == null) bgm.preservesPitch = bgm.__preservesPitch; else if (usePitch) bgm.preservesPitch = false; else bgm.preservesPitch = true; core.musicStatus.bgmUsePitch = usePitch; @@ -2891,7 +2898,7 @@ control.prototype.setBgmSpeed = function (speed, usePitch) { ////// 暂停背景音乐的播放 ////// control.prototype.pauseBgm = function () { - if (main.mode!='play')return; + if (main.mode != 'play') return; try { if (core.musicStatus.playingBgm) { core.musicStatus.pauseTime = core.material.bgms[core.musicStatus.playingBgm].currentTime; @@ -2908,7 +2915,7 @@ control.prototype.pauseBgm = function () { ////// 恢复背景音乐的播放 ////// control.prototype.resumeBgm = function (resumeTime) { - if (main.mode!='play')return; + if (main.mode != 'play') return; try { var speed = core.musicStatus.bgmSpeed; var usePitch = core.musicStatus.bgmUsePitch; @@ -2935,7 +2942,7 @@ control.prototype.setMusicBtn = function () { ////// 更改背景音乐的播放 ////// control.prototype.triggerBgm = function () { - if (main.mode!='play') return; + if (main.mode != 'play') return; core.musicStatus.bgmStatus = !core.musicStatus.bgmStatus; if (core.musicStatus.bgmStatus) @@ -2948,7 +2955,7 @@ control.prototype.triggerBgm = function () { ////// 播放音频 ////// control.prototype.playSound = function (sound, pitch, callback) { sound = core.getMappedName(sound); - if (main.mode!='play' || !core.musicStatus.soundStatus || !core.material.sounds[sound]) return; + if (main.mode != 'play' || !core.musicStatus.soundStatus || !core.material.sounds[sound]) return; try { if (core.musicStatus.audioContext != null) { var source = core.musicStatus.audioContext.createBufferSource(); @@ -2958,7 +2965,7 @@ control.prototype.playSound = function (sound, pitch, callback) { var id = setTimeout(null); if (pitch && pitch >= 30 && pitch <= 300) { source.playbackRate.setValueAtTime(pitch / 100, 0); - } + } source.onended = function () { delete core.musicStatus.playingSounds[id]; if (callback) callback(); @@ -2975,7 +2982,7 @@ control.prototype.playSound = function (sound, pitch, callback) { } } catch (e) { - console.log("无法播放SE "+sound); + console.log("无法播放SE " + sound); main.log(e); } } @@ -3003,13 +3010,13 @@ control.prototype.stopSound = function (id) { ////// 获得当前正在播放的所有(指定)音效的id列表 ////// control.prototype.getPlayingSounds = function (name) { name = core.getMappedName(name); - return Object.keys(core.musicStatus.playingSounds).filter(function (one){ + return Object.keys(core.musicStatus.playingSounds).filter(function (one) { return name == null || core.musicStatus.playingSounds[one].__name == name }); } ////// 检查bgm状态 ////// -control.prototype.checkBgm = function() { +control.prototype.checkBgm = function () { core.playBgm(core.musicStatus.playingBgm || main.startBgm); } @@ -3026,7 +3033,7 @@ control.prototype.setDisplayScale = function (delta) { // ------ 状态栏,工具栏等相关 ------ // ////// 清空状态栏 ////// -control.prototype.clearStatusBar = function() { +control.prototype.clearStatusBar = function () { Object.keys(core.statusBar).forEach(function (e) { if (core.statusBar[e].innerHTML != null) { core.statusBar[e].innerHTML = " "; @@ -3041,11 +3048,19 @@ control.prototype.clearStatusBar = function() { ////// 更新状态栏 ////// control.prototype.updateStatusBar = function (doNotCheckAutoEvents) { + this.needUpdate = true; + if (!doNotCheckAutoEvents) this.noAutoEvents = false; +} + +control.prototype.updateStatusBar_update = function () { + if (!core.control.needUpdate) return; if (!core.isPlaying() || core.hasFlag('__statistics__')) return; - this.controldata.updateStatusBar(); - if (!doNotCheckAutoEvents) core.checkAutoEvents(); - this._updateStatusBar_setToolboxIcon(); + core.control.updateStatusBar(); + if (!core.control.noAutoEvents) core.checkAutoEvents(); + core.control._updateStatusBar_setToolboxIcon(); core.clearRouteFolding(); + core.control.needUpdate = false; + core.control.noAutoEvents = true; } control.prototype._updateStatusBar_setToolboxIcon = function () { @@ -3131,7 +3146,7 @@ control.prototype.updateHeroIcon = function (name) { // 全身图 var w = core.material.icons.hero.width || 32; var h = core.material.icons.hero.height || 48; - var ratio = Math.min(w / h, 1), width = 32 * ratio, left = 16 - width/2; + var ratio = Math.min(w / h, 1), width = 32 * ratio, left = 16 - width / 2; var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); @@ -3160,36 +3175,36 @@ control.prototype.setToolbarButton = function (useButton) { core.domStyle.toolbarBtn = useButton; if (useButton) { - ["book","fly","toolbox","keyboard","shop","save","load","settings"].forEach(function (t) { + ["book", "fly", "toolbox", "keyboard", "shop", "save", "load", "settings"].forEach(function (t) { core.statusBar.image[t].style.display = 'none'; }); - ["btn1","btn2","btn3","btn4","btn5","btn6","btn7","btn8"].forEach(function (t) { + ["btn1", "btn2", "btn3", "btn4", "btn5", "btn6", "btn7", "btn8"].forEach(function (t) { core.statusBar.image[t].style.display = 'block'; }) main.statusBar.image.btn8.style.filter = core.getLocalStorage('altKey') ? 'sepia(1) contrast(1.5)' : ''; } else { - ["btn1","btn2","btn3","btn4","btn5","btn6","btn7","btn8"].forEach(function (t) { + ["btn1", "btn2", "btn3", "btn4", "btn5", "btn6", "btn7", "btn8"].forEach(function (t) { core.statusBar.image[t].style.display = 'none'; }); - ["book","fly","toolbox","save","load","settings"].forEach(function (t) { + ["book", "fly", "toolbox", "save", "load", "settings"].forEach(function (t) { core.statusBar.image[t].style.display = 'block'; }); core.statusBar.image.keyboard.style.display = core.statusBar.image.shop.style.display - = core.domStyle.isVertical || core.flags.extendToolbar ? "block":"none"; + = core.domStyle.isVertical || core.flags.extendToolbar ? "block" : "none"; } } ////// ------ resize处理 ------ // -control.prototype._shouldDisplayStatus = function(id) { +control.prototype._shouldDisplayStatus = function (id) { if (id == null) { var toDraw = [], status = core.dom.status; - for (var i = 0; i= v*(CANVAS_WIDTH + BAR_WIDTH) && horizontalMaxRatio >= v) { + if (clientWidth - 3 * BORDER >= v * (CANVAS_WIDTH + BAR_WIDTH) && horizontalMaxRatio >= v) { core.domStyle.availableScale.push(v); } }); @@ -3281,7 +3296,7 @@ control.prototype.resize = function() { var col = statusCanvas ? statusCanvasRows : Math.ceil(count / 3); if (col > 5) { if (statusCanvas) alert("自绘状态栏的在竖屏下的行数应不超过5!"); - else alert("当前状态栏数目("+count+")大于15,请调整到不超过15以避免手机端出现显示问题。"); + else alert("当前状态栏数目(" + count + ")大于15,请调整到不超过15以避免手机端出现显示问题。"); } var globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute; @@ -3365,17 +3380,17 @@ control.prototype._resize_canvas = function (obj) { // resize bigmap core.bigmap.canvas.forEach(function (cn) { var ratio = core.canvas[cn].canvas.hasAttribute('isHD') ? core.domStyle.ratio : 1; - core.canvas[cn].canvas.style.width = core.canvas[cn].canvas.width / ratio * core.domStyle.scale + "px"; - core.canvas[cn].canvas.style.height = core.canvas[cn].canvas.height / ratio * core.domStyle.scale + "px"; + core.canvas[cn].canvas.style.width = core.canvas[cn].canvas.width / ratio * core.domStyle.scale + "px"; + core.canvas[cn].canvas.style.height = core.canvas[cn].canvas.height / ratio * core.domStyle.scale + "px"; }); // resize dynamic canvas for (var name in core.dymCanvas) { var ctx = core.dymCanvas[name], canvas = ctx.canvas; var ratio = canvas.hasAttribute('isHD') ? core.domStyle.ratio : 1; - canvas.style.width = canvas.width / ratio * core.domStyle.scale + "px"; - canvas.style.height = canvas.height / ratio * core.domStyle.scale + "px"; - canvas.style.left = parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px"; - canvas.style.top = parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px"; + canvas.style.width = canvas.width / ratio * core.domStyle.scale + "px"; + canvas.style.height = canvas.height / ratio * core.domStyle.scale + "px"; + canvas.style.left = parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px"; + canvas.style.top = parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px"; } // resize next main.dom.next.style.width = main.dom.next.style.height = 5 * core.domStyle.scale + "px"; @@ -3414,7 +3429,7 @@ control.prototype._resize_statusBar = function (obj) { } else { core.dom.statusCanvas.style.width = obj.BAR_WIDTH * core.domStyle.scale + "px"; - core.dom.statusCanvas.style.height = obj.outerSize - 2 * obj.BORDER + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px"; + core.dom.statusCanvas.style.height = obj.outerSize - 2 * obj.BORDER + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px"; core.maps._setHDCanvasSize(core.dom.statusCanvasCtx, obj.BAR_WIDTH, obj.CANVAS_WIDTH + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT + obj.BORDER : 0)); } core.dom.statusCanvas.style.display = core.flags.statusCanvas ? "block" : "none"; @@ -3425,13 +3440,13 @@ control.prototype._resize_status = function (obj) { if (core.domStyle.isVertical) { statusHeight = 32 * core.domStyle.scale * 0.8; } else { - statusHeight = (obj.extendToolbar ? core.__SIZE__ : core.__HALF_SIZE__ + 3) / obj.count * 32 * core.domStyle.scale * 0.8; + statusHeight = (obj.extendToolbar ? core.__SIZE__ : core.__HALF_SIZE__ + 3) / obj.count * 32 * core.domStyle.scale * 0.8; } // status for (var i = 0; i < core.dom.status.length; ++i) { var id = core.dom.status[i].id, style = core.dom.status[i].style; - if (id.endsWith("Col")) id = id.substring(0, id.length-3); - style.display = core.flags.statusCanvas || obj.statusDisplayArr.indexOf(id) < 0 ? 'none': 'block'; + if (id.endsWith("Col")) id = id.substring(0, id.length - 3); + style.display = core.flags.statusCanvas || obj.statusDisplayArr.indexOf(id) < 0 ? 'none' : 'block'; style.margin = 3 * core.domStyle.scale + "px"; style.height = statusHeight + "px"; style.maxWidth = obj.BAR_WIDTH * core.domStyle.scale * (core.domStyle.isVertical ? 0.95 : 1) + obj.BORDER + "px"; @@ -3447,7 +3462,7 @@ control.prototype._resize_status = function (obj) { core.dom.statusTexts[i].style.color = core.arrayToRGBA(obj.globalAttribute.statusBarColor); } // keys - if (core.flags.statusBarItems.indexOf('enableGreenKey')>=0) { + if (core.flags.statusBarItems.indexOf('enableGreenKey') >= 0) { core.dom.keyCol.style.fontSize = '0.75em'; core.statusBar.greenKey.style.display = ''; } else { diff --git a/libs/thirdparty/browser-polyfill.min.js b/libs/thirdparty/browser-polyfill.min.js deleted file mode 100644 index 79447613..00000000 --- a/libs/thirdparty/browser-polyfill.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function t(e,n,r){function o(s,c){if(!n[s]){if(!e[s]){var u="function"==typeof require&&require;if(!c&&u)return u(s,!0);if(i)return i(s,!0);var a=new Error("Cannot find module '"+s+"'");throw a.code="MODULE_NOT_FOUND",a}var f=n[s]={exports:{}};e[s][0].call(f.exports,function(t){var n=e[s][1][t];return o(n?n:t)},f,f.exports,t,e,n,r)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s$;$++)if((u||$ in d)&&(f=d[$],l=p(f,$,h),t))if(e)v[$]=l;else if(l)switch(t){case 3:return!0;case 5:return f;case 6:return $;case 2:v.push(f)}else if(s)return!1;return c?-1:i||s?s:v}}},{"./$":16,"./$.ctx":11}],5:[function(t,e){function n(t,e,n){if(!t)throw TypeError(n?e+n:e)}var r=t("./$");n.def=r.assertDefined,n.fn=function(t){if(!r.isFunction(t))throw TypeError(t+" is not a function!");return t},n.obj=function(t){if(!r.isObject(t))throw TypeError(t+" is not an object!");return t},n.inst=function(t,e,n){if(!(t instanceof e))throw TypeError(n+": use the 'new' operator!");return t},e.exports=n},{"./$":16}],6:[function(t,e){var n=t("./$");e.exports=Object.assign||function(t){for(var e=Object(n.assertDefined(t)),r=arguments.length,o=1;r>o;)for(var i,s=n.ES5Object(arguments[o++]),c=n.getKeys(s),u=c.length,a=0;u>a;)e[i=c[a++]]=s[i];return e}},{"./$":16}],7:[function(t,e){function n(t){return i.call(t).slice(8,-1)}var r=t("./$"),o=t("./$.wks")("toStringTag"),i={}.toString;n.classof=function(t){var e,r;return void 0==t?void 0===t?"Undefined":"Null":"string"==typeof(r=(e=Object(t))[o])?r:n(e)},n.set=function(t,e,n){t&&!r.has(t=n?t:t.prototype,o)&&r.hide(t,o,e)},e.exports=n},{"./$":16,"./$.wks":26}],8:[function(t,e){"use strict";function n(t,e){if(!l(t))return("string"==typeof t?"S":"P")+t;if(p(t))return"F";if(!a(t,g)){if(!e)return"E";h(t,g,++w)}return"O"+t[g]}function r(t,e){var r,o=n(e);if("F"!=o)return t[$][o];for(r=t[y];r;r=r.n)if(r.k==e)return r}var o=t("./$"),i=t("./$.ctx"),s=t("./$.uid").safe,c=t("./$.assert"),u=t("./$.iter"),a=o.has,f=o.set,l=o.isObject,h=o.hide,d=u.step,p=Object.isFrozen||o.core.Object.isFrozen,g=s("id"),$=s("O1"),v=s("last"),y=s("first"),m=s("iter"),b=o.DESC?s("size"):"size",w=0;e.exports={getConstructor:function(t,e,n){function s(r){var i=c.inst(this,s,t);f(i,$,o.create(null)),f(i,b,0),f(i,v,void 0),f(i,y,void 0),void 0!=r&&u.forOf(r,e,i[n],i)}return o.mix(s.prototype,{clear:function(){for(var t=this,e=t[$],n=t[y];n;n=n.n)n.r=!0,n.p&&(n.p=n.p.n=void 0),delete e[n.i];t[y]=t[v]=void 0,t[b]=0},"delete":function(t){var e=this,n=r(e,t);if(n){var o=n.n,i=n.p;delete e[$][n.i],n.r=!0,i&&(i.n=o),o&&(o.p=i),e[y]==n&&(e[y]=o),e[v]==n&&(e[v]=i),e[b]--}return!!n},forEach:function(t){for(var e,n=i(t,arguments[1],3);e=e?e.n:this[y];)for(n(e.v,e.k,this);e&&e.r;)e=e.p},has:function(t){return!!r(this,t)}}),o.DESC&&o.setDesc(s.prototype,"size",{get:function(){return c.def(this[b])}}),s},def:function(t,e,o){var i,s,c=r(t,e);return c?c.v=o:(t[v]=c={i:s=n(e,!0),k:e,v:o,p:i=t[v],n:void 0,r:!1},t[y]||(t[y]=c),i&&(i.n=c),t[b]++,"F"!=s&&(t[$][s]=c)),t},getEntry:r,getIterConstructor:function(){return function(t,e){f(this,m,{o:t,k:e})}},next:function(){for(var t=this[m],e=t.k,n=t.l;n&&n.r;)n=n.p;return t.o&&(t.l=n=n?n.n:t.o[y])?"key"==e?d(0,n.k):"value"==e?d(0,n.v):d(0,[n.k,n.v]):(t.o=void 0,d(1))}}},{"./$":16,"./$.assert":5,"./$.ctx":11,"./$.iter":15,"./$.uid":24}],9:[function(t,e){"use strict";function n(t,e){return v.call(t.array,function(t){return t[0]===e})}function r(t){return t[g]||f(t,g,{array:[],get:function(t){var e=n(this,t);return e?e[1]:void 0},has:function(t){return!!n(this,t)},set:function(t,e){var r=n(this,t);r?r[1]=e:this.array.push([t,e])},"delete":function(t){var e=y.call(this.array,function(e){return e[0]===t});return~e&&this.array.splice(e,1),!!~e}})[g]}var o=t("./$"),i=t("./$.uid").safe,s=t("./$.assert"),c=t("./$.iter").forOf,u=o.has,a=o.isObject,f=o.hide,l=Object.isFrozen||o.core.Object.isFrozen,h=0,d=i("id"),p=i("weak"),g=i("leak"),$=t("./$.array-methods"),v=$(5),y=$(6);e.exports={getConstructor:function(t,e,n){function i(r){o.set(s.inst(this,i,t),d,h++),void 0!=r&&c(r,e,this[n],this)}return o.mix(i.prototype,{"delete":function(t){return a(t)?l(t)?r(this)["delete"](t):u(t,p)&&u(t[p],this[d])&&delete t[p][this[d]]:!1},has:function(t){return a(t)?l(t)?r(this).has(t):u(t,p)&&u(t[p],this[d]):!1}}),i},def:function(t,e,n){return l(s.obj(e))?r(t).set(e,n):(u(e,p)||f(e,p,{}),e[p][t[d]]=n),t},leakStore:r,WEAK:p,ID:d}},{"./$":16,"./$.array-methods":4,"./$.assert":5,"./$.iter":15,"./$.uid":24}],10:[function(t,e){"use strict";var n=t("./$"),r=t("./$.def"),o=t("./$.iter"),i=t("./$.assert").inst;e.exports=function(e,s,c,u,a){function f(t,e){var r=p[t];n.FW&&(p[t]=function(t,n){var o=r.call(this,0===t?0:t,n);return e?this:o})}var l=n.g[e],h=l,d=u?"set":"add",p=h&&h.prototype,g={};if(n.isFunction(h)&&(a||!o.BUGGY&&p.forEach&&p.entries)){var $,v=new h,y=v[d](a?{}:-0,1);(o.fail(function(t){new h(t)})||o.DANGER_CLOSING)&&(h=function(t){i(this,h,e);var n=new l;return void 0!=t&&o.forOf(t,u,n[d],n),n},h.prototype=p,n.FW&&(p.constructor=h)),a||v.forEach(function(t,e){$=1/e===-1/0}),$&&(f("delete"),f("has"),u&&f("get")),($||y!==v)&&f(d,!0)}else h=c.getConstructor(e,u,d),n.mix(h.prototype,s);return t("./$.cof").set(h,e),t("./$.species")(h),g[e]=h,r(r.G+r.W+r.F*(h!=l),g),a||o.std(h,e,c.getIterConstructor(),c.next,u?"key+value":"value",!u,!0),h}},{"./$":16,"./$.assert":5,"./$.cof":7,"./$.def":12,"./$.iter":15,"./$.species":21}],11:[function(t,e){var n=t("./$.assert").fn;e.exports=function(t,e,r){if(n(t),~r&&void 0===e)return t;switch(r){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},{"./$.assert":5}],12:[function(t,e){function n(t,e){return function(){return t.apply(e,arguments)}}function r(t,e,u){var a,f,l,h,d=t&r.G,p=d?i:t&r.S?i[e]:(i[e]||{}).prototype,g=d?s:s[e]||(s[e]={});d&&(u=e);for(a in u)f=!(t&r.F)&&p&&a in p,l=(f?p:u)[a],h=t&r.B&&f?n(l,i):t&r.P&&c(l)?n(Function.call,l):l,p&&!f&&(d?p[a]=l:delete p[a]&&o.hide(p,a,l)),g[a]!=l&&o.hide(g,a,h)}var o=t("./$"),i=o.g,s=o.core,c=o.isFunction;i.core=s,r.F=1,r.G=2,r.S=4,r.P=8,r.B=16,r.W=32,e.exports=r},{"./$":16}],13:[function(t,e){e.exports=function(t){return t.FW=!0,t.path=t.g,t}},{}],14:[function(t,e){e.exports=function(t,e,n){var r=void 0===n;switch(e.length){case 0:return r?t():t.call(n);case 1:return r?t(e[0]):t.call(n,e[0]);case 2:return r?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return r?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return r?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3]);case 5:return r?t(e[0],e[1],e[2],e[3],e[4]):t.call(n,e[0],e[1],e[2],e[3],e[4])}return t.apply(n,e)}},{}],15:[function(t,e){"use strict";function n(t,e){c.hide(t,h,e),d in[]&&c.hide(t,d,e)}function r(t,e,r,o){var i=t.prototype,s=i[h]||i[d]||o&&i[o]||r;if(c.FW&&n(i,s),s!==r){var u=c.getProto(s.call(new t));a.set(u,e+" Iterator",!0),c.FW&&c.has(i,d)&&n(u,c.that)}return p[e]=s,p[e+" Iterator"]=c.that,s}function o(t){var e=c.g.Symbol,n=t[e&&e.iterator||d],r=n||t[h]||p[a.classof(t)];return l(r.call(t))}function i(t){var e=t["return"];void 0!==e&&l(e.call(t))}function s(t,e,n,r){try{return r?e(l(n)[0],n[1]):e(n)}catch(o){throw i(t),o}}var c=t("./$"),u=t("./$.ctx"),a=t("./$.cof"),f=t("./$.def"),l=t("./$.assert").obj,h=t("./$.wks")("iterator"),d="@@iterator",p={},g={},$="keys"in[]&&!("next"in[].keys());n(g,c.that);var v=!0;!function(){try{var t=[1].keys();t["return"]=function(){v=!1},Array.from(t,function(){throw 2})}catch(e){}}();var y=e.exports={BUGGY:$,DANGER_CLOSING:v,fail:function(t){var e=!0;try{var n=[[{},1]],r=n[h](),o=r.next;r.next=function(){return e=!1,o.call(this)},n[h]=function(){return r},t(n)}catch(i){}return e},Iterators:p,prototype:g,step:function(t,e){return{value:e,done:!!t}},stepCall:s,close:i,is:function(t){var e=Object(t),n=c.g.Symbol,r=n&&n.iterator||d;return r in e||h in e||c.has(p,a.classof(e))},get:o,set:n,create:function(t,e,n,r){t.prototype=c.create(r||y.prototype,{next:c.desc(1,n)}),a.set(t,e+" Iterator")},define:r,std:function(t,e,n,o,i,s,u){function a(t){return function(){return new n(this,t)}}y.create(n,e,o);var l,h,d=a("key+value"),p=a("value"),g=t.prototype;if("value"==i?p=r(t,e,p,"values"):d=r(t,e,d,"entries"),i&&(l={entries:d,keys:s?p:a("key"),values:p},f(f.P+f.F*$,e,l),u))for(h in l)h in g||c.hide(g,h,l[h])},forOf:function(t,e,n,r){for(var c,a=o(t),f=u(n,r,e?2:1);!(c=a.next()).done;)if(s(a,f,c.value,e)===!1)return i(a)}}},{"./$":16,"./$.assert":5,"./$.cof":7,"./$.ctx":11,"./$.def":12,"./$.wks":26}],16:[function(t,e){"use strict";function n(t){return isNaN(t=+t)?0:(t>0?p:d)(t)}function r(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}function o(t,e,n){return t[e]=n,t}function i(t){return v?function(e,n,o){return m.setDesc(e,n,r(t,o))}:o}function s(t){return null!==t&&("object"==typeof t||"function"==typeof t)}function c(t){return"function"==typeof t}function u(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}var a="undefined"!=typeof self?self:Function("return this")(),f={},l=Object.defineProperty,h={}.hasOwnProperty,d=Math.ceil,p=Math.floor,g=Math.max,$=Math.min,v=!!function(){try{return 2==l({},"a",{get:function(){return 2}}).a}catch(t){}}(),y=i(1),m=e.exports=t("./$.fw")({g:a,core:f,html:a.document&&document.documentElement,isObject:s,isFunction:c,it:function(t){return t},that:function(){return this},toInteger:n,toLength:function(t){return t>0?$(n(t),9007199254740991):0},toIndex:function(t,e){return t=n(t),0>t?g(t+e,0):$(t,e)},has:function(t,e){return h.call(t,e)},create:Object.create,getProto:Object.getPrototypeOf,DESC:v,desc:r,getDesc:Object.getOwnPropertyDescriptor,setDesc:l,getKeys:Object.keys,getNames:Object.getOwnPropertyNames,getSymbols:Object.getOwnPropertySymbols,assertDefined:u,ES5Object:Object,toObject:function(t){return m.ES5Object(u(t))},hide:y,def:i(0),set:a.Symbol?o:y,mix:function(t,e){for(var n in e)y(t,n,e[n]);return t},each:[].forEach});"undefined"!=typeof __e&&(__e=f),"undefined"!=typeof __g&&(__g=a)},{"./$.fw":13}],17:[function(t,e){var n=t("./$");e.exports=function(t,e){for(var r,o=n.toObject(t),i=n.getKeys(o),s=i.length,c=0;s>c;)if(o[r=i[c++]]===e)return r}},{"./$":16}],18:[function(t,e){var n=t("./$"),r=t("./$.assert").obj;e.exports=function(t){return r(t),n.getSymbols?n.getNames(t).concat(n.getSymbols(t)):n.getNames(t)}},{"./$":16,"./$.assert":5}],19:[function(t,e){"use strict";e.exports=function(t,e,n){var r=e===Object(e)?function(t){return e[t]}:e;return function(e){return String(n?e:this).replace(t,r)}}},{}],20:[function(t,e){var n=t("./$"),r=t("./$.assert");e.exports=Object.setPrototypeOf||("__proto__"in{}?function(e,o){try{o=t("./$.ctx")(Function.call,n.getDesc(Object.prototype,"__proto__").set,2),o({},[])}catch(i){e=!0}return function(t,i){return r.obj(t),r(null===i||n.isObject(i),i,": can't set as prototype!"),e?t.__proto__=i:o(t,i),t}}():void 0)},{"./$":16,"./$.assert":5,"./$.ctx":11}],21:[function(t,e){var n=t("./$");e.exports=function(e){n.DESC&&n.FW&&n.setDesc(e,t("./$.wks")("species"),{configurable:!0,get:n.that})}},{"./$":16,"./$.wks":26}],22:[function(t,e){"use strict";var n=t("./$");e.exports=function(t){return function(e){var r,o,i=String(n.assertDefined(this)),s=n.toInteger(e),c=i.length;return 0>s||s>=c?t?"":void 0:(r=i.charCodeAt(s),55296>r||r>56319||s+1===c||(o=i.charCodeAt(s+1))<56320||o>57343?t?i.charAt(s):r:t?i.slice(s,s+2):(r-55296<<10)+(o-56320)+65536)}}},{"./$":16}],23:[function(t,e){"use strict";function n(){var t=+this;if(c.has(m,t)){var e=m[t];delete m[t],e()}}function r(t){n.call(t.data)}var o,i,s,c=t("./$"),u=t("./$.ctx"),a=t("./$.cof"),f=t("./$.invoke"),l=c.g,h=c.isFunction,d=l.setImmediate,p=l.clearImmediate,g=l.postMessage,$=l.addEventListener,v=l.MessageChannel,y=0,m={},b="onreadystatechange";h(d)&&h(p)||(d=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return m[++y]=function(){f(h(t)?t:Function(t),e)},o(y),y},p=function(t){delete m[t]},"process"==a(l.process)?o=function(t){l.process.nextTick(u(n,t,1))}:$&&h(g)&&!c.g.importScripts?(o=function(t){g(t,"*")},$("message",r,!1)):h(v)?(i=new v,s=i.port2,i.port1.onmessage=r,o=u(s.postMessage,s,1)):o=c.g.document&&b in document.createElement("script")?function(t){c.html.appendChild(document.createElement("script"))[b]=function(){c.html.removeChild(this),n.call(t)}}:function(t){setTimeout(u(n,t,1),0)}),e.exports={set:d,clear:p}},{"./$":16,"./$.cof":7,"./$.ctx":11,"./$.invoke":14}],24:[function(t,e){function n(t){return"Symbol("+t+")_"+(++r+Math.random()).toString(36)}var r=0;n.safe=t("./$").g.Symbol||n,e.exports=n},{"./$":16}],25:[function(t,e){var n=t("./$"),r=t("./$.wks")("unscopables");!n.FW||r in[]||n.hide(Array.prototype,r,{}),e.exports=function(t){n.FW&&([][r][t]=!0)}},{"./$":16,"./$.wks":26}],26:[function(t,e){var n=t("./$").g,r={};e.exports=function(e){return r[e]||(r[e]=n.Symbol&&n.Symbol[e]||t("./$.uid").safe("Symbol."+e))}},{"./$":16,"./$.uid":24}],27:[function(t){"use strict";var e=t("./$"),n=t("./$.def"),r=e.toIndex;n(n.P,"Array",{copyWithin:function(t,n){var o=Object(e.assertDefined(this)),i=e.toLength(o.length),s=r(t,i),c=r(n,i),u=arguments[2],a=void 0===u?i:r(u,i),f=Math.min(a-c,i-s),l=1;for(s>c&&c+f>s&&(l=-1,c=c+f-1,s=s+f-1);f-->0;)c in o?o[s]=o[c]:delete o[s],s+=l,c+=l;return o}}),t("./$.unscope")("copyWithin")},{"./$":16,"./$.def":12,"./$.unscope":25}],28:[function(t){"use strict";var e=t("./$"),n=t("./$.def"),r=e.toIndex;n(n.P,"Array",{fill:function(t){for(var n=Object(e.assertDefined(this)),o=e.toLength(n.length),i=r(arguments[1],o),s=arguments[2],c=void 0===s?o:r(s,o);c>i;)n[i++]=t;return n}}),t("./$.unscope")("fill")},{"./$":16,"./$.def":12,"./$.unscope":25}],29:[function(t){var e=t("./$.def");e(e.P,"Array",{findIndex:t("./$.array-methods")(6)}),t("./$.unscope")("findIndex")},{"./$.array-methods":4,"./$.def":12,"./$.unscope":25}],30:[function(t){var e=t("./$.def");e(e.P,"Array",{find:t("./$.array-methods")(5)}),t("./$.unscope")("find")},{"./$.array-methods":4,"./$.def":12,"./$.unscope":25}],31:[function(t){var e=t("./$"),n=t("./$.ctx"),r=t("./$.def"),o=t("./$.iter"),i=o.stepCall;r(r.S+r.F*o.DANGER_CLOSING,"Array",{from:function(t){var r,s,c,u,a=Object(e.assertDefined(t)),f=arguments[1],l=void 0!==f,h=l?n(f,arguments[2],2):void 0,d=0;if(o.is(a))for(u=o.get(a),s=new("function"==typeof this?this:Array);!(c=u.next()).done;d++)s[d]=l?i(u,h,[c.value,d],!0):c.value;else for(s=new("function"==typeof this?this:Array)(r=e.toLength(a.length));r>d;d++)s[d]=l?h(a[d],d):a[d];return s.length=d,s}})},{"./$":16,"./$.ctx":11,"./$.def":12,"./$.iter":15}],32:[function(t){var e=t("./$"),n=t("./$.unscope"),r=t("./$.uid").safe("iter"),o=t("./$.iter"),i=o.step,s=o.Iterators;o.std(Array,"Array",function(t,n){e.set(this,r,{o:e.toObject(t),i:0,k:n})},function(){var t=this[r],e=t.o,n=t.k,o=t.i++;return!e||o>=e.length?(t.o=void 0,i(1)):"key"==n?i(0,o):"value"==n?i(0,e[o]):i(0,[o,e[o]])},"value"),s.Arguments=s.Array,n("keys"),n("values"),n("entries")},{"./$":16,"./$.iter":15,"./$.uid":24,"./$.unscope":25}],33:[function(t){var e=t("./$.def");e(e.S,"Array",{of:function(){for(var t=0,e=arguments.length,n=new("function"==typeof this?this:Array)(e);e>t;)n[t]=arguments[t++];return n.length=e,n}})},{"./$.def":12}],34:[function(t){t("./$.species")(Array)},{"./$.species":21}],35:[function(t){"use strict";var e=t("./$"),n="name",r=e.setDesc,o=Function.prototype;n in o||e.FW&&e.DESC&&r(o,n,{configurable:!0,get:function(){var t=String(this).match(/^\s*function ([^ (]*)/),o=t?t[1]:"";return e.has(this,n)||r(this,n,e.desc(5,o)),o},set:function(t){e.has(this,n)||r(this,n,e.desc(0,t))}})},{"./$":16}],36:[function(t){"use strict";var e=t("./$.collection-strong");t("./$.collection")("Map",{get:function(t){var n=e.getEntry(this,t);return n&&n.v},set:function(t,n){return e.def(this,0===t?0:t,n)}},e,!0)},{"./$.collection":10,"./$.collection-strong":8}],37:[function(t){function e(t){return isFinite(t=+t)&&0!=t?0>t?-e(-t):a(t+f(t*t+1)):t}function n(t){return 0==(t=+t)?t:t>-1e-6&&1e-6>t?t+t*t/2:u(t)-1}var r=1/0,o=t("./$.def"),i=Math.E,s=Math.pow,c=Math.abs,u=Math.exp,a=Math.log,f=Math.sqrt,l=Math.ceil,h=Math.floor,d=Math.sign||function(t){return 0==(t=+t)||t!=t?t:0>t?-1:1};o(o.S,"Math",{acosh:function(t){return(t=+t)<1?0/0:isFinite(t)?a(t/i+f(t+1)*f(t-1)/i)+1:t},asinh:e,atanh:function(t){return 0==(t=+t)?t:a((1+t)/(1-t))/2},cbrt:function(t){return d(t=+t)*s(c(t),1/3)},clz32:function(t){return(t>>>=0)?32-t.toString(2).length:32},cosh:function(t){return(u(t=+t)+u(-t))/2},expm1:n,fround:function(t){return new Float32Array([t])[0]},hypot:function(){for(var t,e=0,n=arguments.length,o=n,i=Array(n),c=-r;n--;){if(t=i[n]=+arguments[n],t==r||t==-r)return r;t>c&&(c=t)}for(c=t||1;o--;)e+=s(i[o]/c,2);return c*f(e)},imul:function(t,e){var n=65535,r=+t,o=+e,i=n&r,s=n&o;return 0|i*s+((n&r>>>16)*s+i*(n&o>>>16)<<16>>>0)},log1p:function(t){return(t=+t)>-1e-8&&1e-8>t?t-t*t/2:a(1+t)},log10:function(t){return a(t)/Math.LN10},log2:function(t){return a(t)/Math.LN2},sign:d,sinh:function(t){return c(t=+t)<1?(n(t)-n(-t))/2:(u(t-1)-u(-t-1))*(i/2)},tanh:function(t){var e=n(t=+t),o=n(-t);return e==r?1:o==r?-1:(e-o)/(u(t)+u(-t))},trunc:function(t){return(t>0?h:l)(t)}})},{"./$.def":12}],38:[function(t){"use strict";function e(t){var e,n;if(i(e=t.valueOf)&&!o(n=e.call(t)))return n;if(i(e=t.toString)&&!o(n=e.call(t)))return n;throw TypeError("Can't convert object to number")}function n(t){if(o(t)&&(t=e(t)),"string"==typeof t&&t.length>2&&48==t.charCodeAt(0)){var n=!1;switch(t.charCodeAt(1)){case 66:case 98:n=!0;case 79:case 111:return parseInt(t.slice(2),n?2:8)}}return+t}var r=t("./$"),o=r.isObject,i=r.isFunction,s="Number",c=r.g[s],u=c,a=c.prototype;!r.FW||c("0o1")&&c("0b1")||(c=function f(t){return this instanceof f?new u(n(t)):n(t)},r.each.call(r.DESC?r.getNames(u):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),function(t){r.has(u,t)&&!r.has(c,t)&&r.setDesc(c,t,r.getDesc(u,t))}),c.prototype=a,a.constructor=c,r.hide(r.g,s,c))},{"./$":16}],39:[function(t){function e(t){return!n.isObject(t)&&isFinite(t)&&i(t)===t}var n=t("./$"),r=t("./$.def"),o=Math.abs,i=Math.floor,s=9007199254740991;r(r.S,"Number",{EPSILON:Math.pow(2,-52),isFinite:function(t){return"number"==typeof t&&isFinite(t)},isInteger:e,isNaN:function(t){return t!=t},isSafeInteger:function(t){return e(t)&&o(t)<=s},MAX_SAFE_INTEGER:s,MIN_SAFE_INTEGER:-s,parseFloat:parseFloat,parseInt:parseInt})},{"./$":16,"./$.def":12}],40:[function(t){var e=t("./$.def");e(e.S,"Object",{assign:t("./$.assign")})},{"./$.assign":6,"./$.def":12}],41:[function(t){var e=t("./$.def");e(e.S,"Object",{is:function(t,e){return t===e?0!==t||1/t===1/e:t!=t&&e!=e}})},{"./$.def":12}],42:[function(t){var e=t("./$.def");e(e.S,"Object",{setPrototypeOf:t("./$.set-proto")})},{"./$.def":12,"./$.set-proto":20}],43:[function(t){function e(t,e){var s=(n.core.Object||{})[t]||Object[t],c=0,u={};u[t]=1==e?function(t){return o(t)?s(t):t}:2==e?function(t){return o(t)?s(t):!0}:3==e?function(t){return o(t)?s(t):!1}:4==e?function(t,e){return s(i(t),e)}:5==e?function(t){return s(Object(n.assertDefined(t)))}:function(t){return s(i(t))};try{s("z")}catch(a){c=1}r(r.S+r.F*c,"Object",u)}var n=t("./$"),r=t("./$.def"),o=n.isObject,i=n.toObject;e("freeze",1),e("seal",1),e("preventExtensions",1),e("isFrozen",2),e("isSealed",2),e("isExtensible",3),e("getOwnPropertyDescriptor",4),e("getPrototypeOf",5),e("keys"),e("getOwnPropertyNames")},{"./$":16,"./$.def":12}],44:[function(t){"use strict";var e=t("./$"),n=t("./$.cof"),r={};r[t("./$.wks")("toStringTag")]="z",e.FW&&"z"!=n(r)&&e.hide(Object.prototype,"toString",function(){return"[object "+n.classof(this)+"]"})},{"./$":16,"./$.cof":7,"./$.wks":26}],45:[function(t){"use strict";function e(t){var e=w(t)[a];return void 0!=e?e:t}var n,r=t("./$"),o=t("./$.ctx"),i=t("./$.cof"),s=t("./$.def"),c=t("./$.assert"),u=t("./$.iter"),a=t("./$.wks")("species"),f=t("./$.uid").safe("record"),l=u.forOf,h="Promise",d=r.g,p=d.process,g=p&&p.nextTick||t("./$.task").set,$=d[h],v=$,y=r.isFunction,m=r.isObject,b=c.fn,w=c.obj;y($)&&y($.resolve)&&$.resolve(n=new $(function(){}))==n||function(){function t(t){var e;return m(t)&&(e=t.then),y(e)?e:!1}function e(t){var n,r=t[f],o=r.c,i=0;if(r.h)return!0;for(;o.length>i;)if(n=o[i++],n.fail||e(n.P))return!0}function n(n,r){var o=n.c;(r||o.length)&&g(function(){var s=n.p,c=n.v,u=1==n.s,a=0;if(r&&!e(s))setTimeout(function(){e(s)||("process"==i(p)?p.emit("unhandledRejection",c,s):d.console&&y(console.error)&&console.error("Unhandled promise rejection",c))},1e3);else for(;o.length>a;)!function(e){var r,o,i=u?e.ok:e.fail;try{i?(u||(n.h=!0),r=i===!0?c:i(c),r===e.P?e.rej(TypeError(h+"-chain cycle")):(o=t(r))?o.call(r,e.res,e.rej):e.res(r)):e.rej(c)}catch(s){e.rej(s)}}(o[a++]);o.length=0})}function s(t){var e=this;e.d||(e.d=!0,e=e.r||e,e.v=t,e.s=2,n(e,!0))}function u(e){var r,i,c=this;if(!c.d){c.d=!0,c=c.r||c;try{(r=t(e))?(i={r:c,d:!1},r.call(e,o(u,i,1),o(s,i,1))):(c.v=e,c.s=1,n(c))}catch(a){s.call(i||{r:c,d:!1},a)}}}$=function(t){b(t);var e={p:c.inst(this,$,h),c:[],s:0,d:!1,v:void 0,h:!1};r.hide(this,f,e);try{t(o(u,e,1),o(s,e,1))}catch(n){s.call(e,n)}},r.mix($.prototype,{then:function(t,e){var r=w(w(this).constructor)[a],o={ok:y(t)?t:!0,fail:y(e)?e:!1},i=o.P=new(void 0!=r?r:$)(function(t,e){o.res=b(t),o.rej=b(e)}),s=this[f];return s.c.push(o),s.s&&n(s),i},"catch":function(t){return this.then(void 0,t)}})}(),s(s.G+s.W+s.F*($!=v),{Promise:$}),s(s.S,h,{reject:function(t){return new(e(this))(function(e,n){n(t)})},resolve:function(t){return m(t)&&f in t&&r.getProto(t)===this.prototype?t:new(e(this))(function(e){e(t)})}}),s(s.S+s.F*(u.fail(function(t){$.all(t)["catch"](function(){})})||u.DANGER_CLOSING),h,{all:function(t){var n=e(this),o=[];return new n(function(e,i){l(t,!1,o.push,o);var s=o.length,c=Array(s);s?r.each.call(o,function(t,r){n.resolve(t).then(function(t){c[r]=t,--s||e(c)},i)}):e(c)})},race:function(t){var n=e(this);return new n(function(e,r){l(t,!1,function(t){n.resolve(t).then(e,r)})})}}),i.set($,h),t("./$.species")($)},{"./$":16,"./$.assert":5,"./$.cof":7,"./$.ctx":11,"./$.def":12,"./$.iter":15,"./$.species":21,"./$.task":23,"./$.uid":24,"./$.wks":26}],46:[function(t){function e(t){var e,n=[];for(e in t)n.push(e);i.set(this,a,{o:t,a:n,i:0})}function n(t){return function(e){v(e);try{return t.apply(void 0,arguments),!0}catch(n){return!1}}}function r(t,e){var n,o=arguments.length<3?t:arguments[2],s=d(v(t),e);return s?i.has(s,"value")?s.value:void 0===s.get?void 0:s.get.call(o):h(n=g(t))?r(n,e,o):void 0}function o(t,e,n){var r,s,c=arguments.length<4?t:arguments[3],u=d(v(t),e);if(!u){if(h(s=g(t)))return o(s,e,n,c);u=i.desc(0)}return i.has(u,"value")?u.writable!==!1&&h(c)?(r=d(c,e)||i.desc(0),r.value=n,p(c,e,r),!0):!1:void 0===u.set?!1:(u.set.call(c,n),!0)}var i=t("./$"),s=t("./$.def"),c=t("./$.set-proto"),u=t("./$.iter"),a=t("./$.uid").safe("iter"),f=u.step,l=t("./$.assert"),h=i.isObject,d=i.getDesc,p=i.setDesc,g=i.getProto,$=Function.apply,v=l.obj,y=Object.isExtensible||i.it;u.create(e,"Object",function(){var t,e=this[a],n=e.a;do if(e.i>=n.length)return f(1);while(!((t=n[e.i++])in e.o));return f(0,t)});var m={apply:t("./$.ctx")(Function.call,$,3),construct:function(t,e){var n=l.fn(arguments.length<3?t:arguments[2]).prototype,r=i.create(h(n)?n:Object.prototype),o=$.call(t,r,e);return h(o)?o:r},defineProperty:n(p),deleteProperty:function(t,e){var n=d(v(t),e);return n&&!n.configurable?!1:delete t[e]},enumerate:function(t){return new e(v(t))},get:r,getOwnPropertyDescriptor:function(t,e){return d(v(t),e)},getPrototypeOf:function(t){return g(v(t))},has:function(t,e){return e in t},isExtensible:function(t){return!!y(v(t))},ownKeys:t("./$.own-keys"),preventExtensions:n(Object.preventExtensions||i.it),set:o};c&&(m.setPrototypeOf=function(t,e){return c(v(t),e),!0}),s(s.G,{Reflect:{}}),s(s.S,"Reflect",m)},{"./$":16,"./$.assert":5,"./$.ctx":11,"./$.def":12,"./$.iter":15,"./$.own-keys":18,"./$.set-proto":20,"./$.uid":24}],47:[function(t){var e=t("./$"),n=t("./$.cof"),r=e.g.RegExp,o=r,i=r.prototype;e.FW&&e.DESC&&(function(){try{return"/a/i"==r(/a/g,"i")}catch(t){}}()||(r=function(t,e){return new o("RegExp"==n(t)&&void 0!==e?t.source:t,e)},e.each.call(e.getNames(o),function(t){t in r||e.setDesc(r,t,{configurable:!0,get:function(){return o[t]},set:function(e){o[t]=e}})}),i.constructor=r,r.prototype=i,e.hide(e.g,"RegExp",r)),"g"!=/./g.flags&&e.setDesc(i,"flags",{configurable:!0,get:t("./$.replacer")(/^.*\/(\w*)$/,"$1")})),t("./$.species")(r)},{"./$":16,"./$.cof":7,"./$.replacer":19,"./$.species":21}],48:[function(t){"use strict";var e=t("./$.collection-strong");t("./$.collection")("Set",{add:function(t){return e.def(this,t=0===t?0:t,t)}},e)},{"./$.collection":10,"./$.collection-strong":8}],49:[function(t){var e=t("./$.def");e(e.P,"String",{codePointAt:t("./$.string-at")(!1)})},{"./$.def":12,"./$.string-at":22}],50:[function(t){"use strict";var e=t("./$"),n=t("./$.cof"),r=t("./$.def"),o=e.toLength;r(r.P,"String",{endsWith:function(t){if("RegExp"==n(t))throw TypeError();var r=String(e.assertDefined(this)),i=arguments[1],s=o(r.length),c=void 0===i?s:Math.min(o(i),s);return t+="",r.slice(c-t.length,c)===t}})},{"./$":16,"./$.cof":7,"./$.def":12}],51:[function(t){var e=t("./$.def"),n=t("./$").toIndex,r=String.fromCharCode;e(e.S,"String",{fromCodePoint:function(){for(var t,e=[],o=arguments.length,i=0;o>i;){if(t=+arguments[i++],n(t,1114111)!==t)throw RangeError(t+" is not a valid code point");e.push(65536>t?r(t):r(((t-=65536)>>10)+55296,t%1024+56320))}return e.join("")}})},{"./$":16,"./$.def":12}],52:[function(t){"use strict";var e=t("./$"),n=t("./$.cof"),r=t("./$.def");r(r.P,"String",{includes:function(t){if("RegExp"==n(t))throw TypeError();return!!~String(e.assertDefined(this)).indexOf(t,arguments[1])}})},{"./$":16,"./$.cof":7,"./$.def":12}],53:[function(t){var e=t("./$").set,n=t("./$.string-at")(!0),r=t("./$.uid").safe("iter"),o=t("./$.iter"),i=o.step;o.std(String,"String",function(t){e(this,r,{o:String(t),i:0})},function(){var t,e=this[r],o=e.o,s=e.i;return s>=o.length?i(1):(t=n.call(o,s),e.i+=t.length,i(0,t))})},{"./$":16,"./$.iter":15,"./$.string-at":22,"./$.uid":24}],54:[function(t){var e=t("./$"),n=t("./$.def");n(n.S,"String",{raw:function(t){for(var n=e.toObject(t.raw),r=e.toLength(n.length),o=arguments.length,i=[],s=0;r>s;)i.push(String(n[s++])),o>s&&i.push(String(arguments[s]));return i.join("")}})},{"./$":16,"./$.def":12}],55:[function(t){"use strict";var e=t("./$"),n=t("./$.def");n(n.P,"String",{repeat:function(t){var n=String(e.assertDefined(this)),r="",o=e.toInteger(t);if(0>o||1/0==o)throw RangeError("Count can't be negative");for(;o>0;(o>>>=1)&&(n+=n))1&o&&(r+=n);return r}})},{"./$":16,"./$.def":12}],56:[function(t){"use strict";var e=t("./$"),n=t("./$.cof"),r=t("./$.def");r(r.P,"String",{startsWith:function(t){if("RegExp"==n(t))throw TypeError();var r=String(e.assertDefined(this)),o=e.toLength(Math.min(arguments[1],r.length));return t+="",r.slice(o,o+t.length)===t}})},{"./$":16,"./$.cof":7,"./$.def":12}],57:[function(t){"use strict";function e(t){var e=$[t]=n.set(n.create(l.prototype),p,t);return n.DESC&&d&&n.setDesc(Object.prototype,t,{configurable:!0,set:function(e){u(this,t,e)}}),e}var n=t("./$"),r=t("./$.cof").set,o=t("./$.uid"),i=t("./$.def"),s=t("./$.keyof"),c=n.has,u=n.hide,a=n.getNames,f=n.toObject,l=n.g.Symbol,h=l,d=!1,p=o.safe("tag"),g={},$={};n.isFunction(l)||(l=function(t){if(this instanceof l)throw TypeError("Symbol is not a constructor");return e(o(t))},u(l.prototype,"toString",function(){return this[p]})),i(i.G+i.W,{Symbol:l});var v={"for":function(t){return c(g,t+="")?g[t]:g[t]=l(t)},keyFor:function(t){return s(g,t)},pure:o.safe,set:n.set,useSetter:function(){d=!0},useSimple:function(){d=!1}};n.each.call("hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),function(n){var r=t("./$.wks")(n);v[n]=l===h?r:e(r)}),d=!0,i(i.S,"Symbol",v),i(i.S+i.F*(l!=h),"Object",{getOwnPropertyNames:function(t){for(var e,n=a(f(t)),r=[],o=0;n.length>o;)c($,e=n[o++])||r.push(e);return r},getOwnPropertySymbols:function(t){for(var e,n=a(f(t)),r=[],o=0;n.length>o;)c($,e=n[o++])&&r.push($[e]);return r}}),r(l,"Symbol"),r(Math,"Math",!0),r(n.g.JSON,"JSON",!0)},{"./$":16,"./$.cof":7,"./$.def":12,"./$.keyof":17,"./$.uid":24,"./$.wks":26}],58:[function(t){"use strict";var e=t("./$"),n=t("./$.collection-weak"),r=n.leakStore,o=n.ID,i=n.WEAK,s=e.has,c=e.isObject,u=Object.isFrozen||e.core.Object.isFrozen,a={},f=t("./$.collection")("WeakMap",{get:function(t){if(c(t)){if(u(t))return r(this).get(t);if(s(t,i))return t[i][this[o]]}},set:function(t,e){return n.def(this,t,e)}},n,!0,!0);e.FW&&7!=(new f).set((Object.freeze||Object)(a),7).get(a)&&e.each.call(["delete","has","get","set"],function(t){var e=f.prototype[t]; -f.prototype[t]=function(n,o){if(c(n)&&u(n)){var i=r(this)[t](n,o);return"set"==t?this:i}return e.call(this,n,o)}})},{"./$":16,"./$.collection":10,"./$.collection-weak":9}],59:[function(t){"use strict";var e=t("./$.collection-weak");t("./$.collection")("WeakSet",{add:function(t){return e.def(this,t,!0)}},e,!1,!0)},{"./$.collection":10,"./$.collection-weak":9}],60:[function(t,e){(function(t){!function(t){"use strict";function n(t,e,n,r){return new s(t,e,n||null,r||[])}function r(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(r){return{type:"throw",arg:r}}}function o(){}function i(){}function s(t,e,n,o){function i(e,o){if(u===m)throw new Error("Generator is already running");if(u===b)return l();for(;;){var i=c.delegate;if(i){var s=r(i.iterator[e],i.iterator,o);if("throw"===s.type){c.delegate=null,e="throw",o=s.arg;continue}e="next",o=h;var a=s.arg;if(!a.done)return u=y,a;c[i.resultName]=a.value,c.next=i.nextLoc,c.delegate=null}if("next"===e){if(u===v&&"undefined"!=typeof o)throw new TypeError("attempt to send "+JSON.stringify(o)+" to newborn generator");u===y?c.sent=o:delete c.sent}else if("throw"===e){if(u===v)throw u=b,o;c.dispatchException(o)&&(e="next",o=h)}else"return"===e&&c.abrupt("return",o);u=m;var s=r(t,n,c);if("normal"===s.type){u=c.done?b:y;var a={value:s.arg,done:c.done};if(s.arg!==w)return a;c.delegate&&"next"===e&&(o=h)}else"throw"===s.type&&(u=b,"next"===e?c.dispatchException(s.arg):o=s.arg)}}var s=e?Object.create(e.prototype):this,c=new a(o),u=v;return s.next=i.bind(s,"next"),s["throw"]=i.bind(s,"throw"),s["return"]=i.bind(s,"return"),s}function c(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function u(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function a(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(c,this),this.reset()}function f(t){if(t){var e=t[p];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,r=function o(){for(;++ne;++e)this[t]=null},stop:function(){this.done=!0;var t=this.tryEntries[0],e=t.completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(t){function e(e,r){return i.type="throw",i.arg=t,n.next=e,!!r}if(this.done)throw t;for(var n=this,r=this.tryEntries.length-1;r>=0;--r){var o=this.tryEntries[r],i=o.completion;if("root"===o.tryLoc)return e("end");if(o.tryLoc<=this.prev){var s=d.call(o,"catchLoc"),c=d.call(o,"finallyLoc");if(s&&c){if(this.prev=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&d.call(r,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc)}},"catch":function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;u(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:f(t),resultName:e,nextLoc:n},w}}}("object"==typeof t?t:"object"==typeof window?window:this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1]); \ No newline at end of file diff --git a/libs/ui.js b/libs/ui.js index 4f552203..aef1417b 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -8,7 +8,7 @@ "use strict"; -function ui() { +function ui () { this._init(); // for convenience this.SIZE = core.__SIZE__; @@ -26,6 +26,7 @@ ui.prototype._init = function () { ////////////////// 地图设置 ui.prototype.getContextByName = function (name) { + if (name instanceof HTMLCanvasElement) return name.getContext('2d'); var canvas = name; if (typeof name == 'string') { if (core.canvas[name]) @@ -50,7 +51,7 @@ ui.prototype._createUIEvent = function () { ui.prototype.clearMap = function (name, x, y, width, height) { if (name == 'all') { for (var m in core.canvas) { - core.canvas[m].clearRect(-32, -32, core.canvas[m].canvas.width+32, core.canvas[m].canvas.height+32); + core.canvas[m].clearRect(-32, -32, core.canvas[m].canvas.width + 32, core.canvas[m].canvas.height + 32); } core.dom.gif.innerHTML = ""; core.removeGlobalAnimate(); @@ -103,7 +104,7 @@ ui.prototype.fillText = function (name, text, x, y, style, font, maxWidth) { var width = 0; for (var i = 0; i < textArray.length; i++) { var subtext = textArray[i]; - if (colorArray[i-1]) ctx.fillStyle = colorArray[i-1].slice(2, -1); + if (colorArray[i - 1]) ctx.fillStyle = colorArray[i - 1].slice(2, -1); ctx.fillText(subtext, x + width, y); width += core.calWidth(ctx, subtext, x, y); } @@ -126,7 +127,7 @@ ui.prototype.setFontForMaxWidth = function (name, text, maxWidth, font) { var font = ctx.font, u = /(\d+)px/.exec(font); if (u == null) return; for (var font_size = parseInt(u[1]); font_size >= 8; font_size--) { - ctx.font = font.replace(/(\d+)px/, font_size+"px"); + ctx.font = font.replace(/(\d+)px/, font_size + "px"); if (ctx.measureText(text).width <= maxWidth) return; } } @@ -176,10 +177,10 @@ ui.prototype.fillRect = function (name, x, y, width, height, style, angle) { ui.prototype._uievent_fillRect = function (data) { this._createUIEvent(); if (data.radius) { - this.fillRoundRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), + this.fillRoundRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), core.calValue(data.radius), data.style, (core.calValue(data.angle) || 0) * Math.PI / 180); } else { - this.fillRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), + this.fillRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.style, (core.calValue(data.angle) || 0) * Math.PI / 180); } } @@ -206,10 +207,10 @@ ui.prototype.strokeRect = function (name, x, y, width, height, style, lineWidth, ui.prototype._uievent_strokeRect = function (data) { this._createUIEvent(); if (data.radius) { - this.strokeRoundRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), + this.strokeRoundRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), core.calValue(data.radius), data.style, data.lineWidth, (core.calValue(data.angle) || 0) * Math.PI / 180); } else { - this.strokeRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), + this.strokeRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.style, data.lineWidth, (core.calValue(data.angle) || 0) * Math.PI / 180); } } @@ -272,7 +273,7 @@ ui.prototype.fillPolygon = function (name, nodes, style) { if (style) core.setFillStyle(name, style); var ctx = this.getContextByName(name); if (!ctx) return; - if (!nodes || nodes.length<3) return; + if (!nodes || nodes.length < 3) return; ctx.beginPath(); for (var i = 0; i < nodes.length; ++i) { var x = core.calValue(nodes[i][0]), y = core.calValue(nodes[i][1]); @@ -294,7 +295,7 @@ ui.prototype.strokePolygon = function (name, nodes, style, lineWidth) { if (lineWidth) core.setLineWidth(name, lineWidth); var ctx = this.getContextByName(name); if (!ctx) return; - if (!nodes || nodes.length<3) return; + if (!nodes || nodes.length < 3) return; ctx.beginPath(); for (var i = 0; i < nodes.length; ++i) { var x = core.calValue(nodes[i][0]), y = core.calValue(nodes[i][1]); @@ -316,7 +317,7 @@ ui.prototype.fillEllipse = function (name, x, y, a, b, angle, style) { var ctx = this.getContextByName(name); if (!ctx) return; ctx.beginPath(); - ctx.ellipse(x, y, a, b, angle, 0, 2*Math.PI); + ctx.ellipse(x, y, a, b, angle, 0, 2 * Math.PI); ctx.fill(); } @@ -337,7 +338,7 @@ ui.prototype.strokeEllipse = function (name, x, y, a, b, angle, style, lineWidth var ctx = this.getContextByName(name); if (!ctx) return; ctx.beginPath(); - ctx.ellipse(x, y, a, b, angle, 0, 2*Math.PI); + ctx.ellipse(x, y, a, b, angle, 0, 2 * Math.PI); ctx.stroke(); } @@ -403,20 +404,20 @@ ui.prototype._uievent_drawLine = function (data) { ////// 在某个canvas上绘制一个箭头 ////// ui.prototype.drawArrow = function (name, x1, y1, x2, y2, style, lineWidth) { - if (x1==x2 && y1==y2) return; + if (x1 == x2 && y1 == y2) return; if (style) core.setStrokeStyle(name, style); if (lineWidth != null) core.setLineWidth(name, lineWidth); var ctx = this.getContextByName(name); if (!ctx) return; var head = 10; - var dx = x2-x1, dy=y2-y1; - var angle = Math.atan2(dy,dx); + var dx = x2 - x1, dy = y2 - y1; + var angle = Math.atan2(dy, dx); ctx.beginPath(); - ctx.moveTo(x1,y1); + ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); - ctx.lineTo(x2-head*Math.cos(angle-Math.PI/6),y2-head*Math.sin(angle-Math.PI/6)); + ctx.lineTo(x2 - head * Math.cos(angle - Math.PI / 6), y2 - head * Math.sin(angle - Math.PI / 6)); ctx.moveTo(x2, y2); - ctx.lineTo(x2-head*Math.cos(angle+Math.PI/6),y2-head*Math.sin(angle+Math.PI/6)); + ctx.lineTo(x2 - head * Math.cos(angle + Math.PI / 6), y2 - head * Math.sin(angle + Math.PI / 6)); ctx.stroke(); } @@ -472,7 +473,7 @@ ui.prototype.setFilter = function (name, filter) { else if (typeof filter === 'string') ctx.filter = filter; else { var x = []; - if (filter.blur > 0) x.push('blur(' + filter.blur +'px)'); + if (filter.blur > 0) x.push('blur(' + filter.blur + 'px)'); if (filter.hue > 0) x.push('hue-rotate(' + filter.hue + 'deg)'); if (filter.grayscale > 0) x.push('grayscale(' + filter.grayscale + ')'); if (filter.invert) x.push('invert(1)'); @@ -525,7 +526,7 @@ ui.prototype._uievent_setAttribute = function (data) { ui.prototype._uievent_setFilter = function (data) { this._createUIEvent(); - this.setFilter('uievent',data); + this.setFilter('uievent', data); } ////// 计算某段文字的宽度 ////// @@ -638,7 +639,7 @@ ui.prototype.drawIcon = function (name, id, x, y, w, h, frame) { if (!info) { // 检查状态栏图标 if (core.statusBar.icons[id] instanceof Image) - info = {image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32}; + info = { image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32 }; else return; } core.drawImage(ctx, info.image, 32 * (info.posX + frame), info.height * info.posY, 32, info.height, x, y, w || 32, h || info.height); @@ -651,7 +652,7 @@ ui.prototype._uievent_drawIcon = function (data) { id = core.calValue(data.id); if (typeof id !== 'string') id = data.id; } catch (e) { id = data.id; } - this.drawIcon('uievent', id, core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.frame||0); + this.drawIcon('uievent', id, core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.frame || 0); } ///////////////// UI绘制 @@ -709,7 +710,7 @@ ui.prototype.drawTip = function (text, id, frame) { if (info == null || !info.image || info.bigImage) { // 检查状态栏图标 if (core.statusBar.icons[id] instanceof Image) { - info = {image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32}; + info = { image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32 }; } else info = null; } @@ -738,28 +739,28 @@ ui.prototype._drawTip_drawOne = function (tip) { ui.prototype.drawText = function (contents, callback) { if (contents != null) return this._drawText_setContent(contents, callback); - if (core.status.event.data.list.length==0) { + if (core.status.event.data.list.length == 0) { var callback = core.status.event.data.callback; core.ui.closePanel(false); if (callback) callback(); return; } - var data=core.status.event.data.list.shift(); + var data = core.status.event.data.list.shift(); if (typeof data == 'string') data = { "text": data }; core.ui.drawTextBox(data.text, data); } ui.prototype._drawText_setContent = function (contents, callback) { // 合并进 insertAction - if ((core.status.event && core.status.event.id=='action') + if ((core.status.event && core.status.event.id == 'action') || (!core.hasFlag('__replayText__') && core.isReplaying())) { - core.insertAction(contents,null,null,callback); + core.insertAction(contents, null, null, callback); return; } if (!(contents instanceof Array)) contents = [contents]; - core.status.event = {'id': 'text', 'data': {'list': contents, 'callback': callback}}; + core.status.event = { 'id': 'text', 'data': { 'list': contents, 'callback': callback } }; core.lockControl(); core.waitHeroToStop(core.drawText); @@ -818,7 +819,7 @@ ui.prototype._getTitleAndIcon = function (content) { ////// 正则处理 \b[up,xxx] 问题 ui.prototype._getPosition = function (content) { var pos = null, px = null, py = null, noPeak = false; - if (core.status.event.id=='action') { + if (core.status.event.id == 'action') { px = core.status.event.data.x; py = core.status.event.data.y; } @@ -829,7 +830,7 @@ ui.prototype._getPosition = function (content) { content = content.replace("\b", "\\b") .replace(/\\b\[(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?]/g, function (s0, s1, s2, s3) { pos = s1; - if (s3 == 'hero' || s1=='hero' && !s3) { + if (s3 == 'hero' || s1 == 'hero' && !s3) { px = core.getHeroLoc('x'); py = core.getHeroLoc('y'); } @@ -840,27 +841,27 @@ ui.prototype._getPosition = function (content) { var str = s3.split(','); px = py = null; if (str.length == 1) { - var follower = core.status.hero.followers[parseInt(str[0])-1]; + var follower = core.status.hero.followers[parseInt(str[0]) - 1]; if (follower) { px = follower.x; py = follower.y; } - } else{ + } else { px = parseInt(str[0]); py = parseInt(str[1]); noPeak = core.getBlockId(px, py) == null; } } - if(pos=='hero' || pos=='this'){ - pos = py==null?'center':(py>core.__HALF_SIZE__? 'up':'down'); + if (pos == 'hero' || pos == 'this') { + pos = py == null ? 'center' : (py > core.__HALF_SIZE__ ? 'up' : 'down'); } return ""; }); - return {content: content, position: pos, px: px, py: py, noPeak: noPeak}; + return { content: content, position: pos, px: px, py: py, noPeak: noPeak }; } ////// 绘制系统选择光标 -ui.prototype._drawWindowSelector = function(background, x, y, w, h) { +ui.prototype._drawWindowSelector = function (background, x, y, w, h) { w = Math.round(w), h = Math.round(h); var ctx = core.ui.createCanvas("_selector", x, y, w, h, 165); this._drawSelector(ctx, background, w, h); @@ -903,53 +904,53 @@ ui.prototype._drawSelector = function (ctx, background, w, h, left, top) { left = left || 0; top = top || 0; // back - core.drawImage(ctx, background, 130, 66, 28, 28, left+2, top+2, w-4, h-4); + core.drawImage(ctx, background, 130, 66, 28, 28, left + 2, top + 2, w - 4, h - 4); // corner - core.drawImage(ctx, background, 128, 64, 2, 2, left, top, 2, 2); - core.drawImage(ctx, background, 158, 64, 2, 2, left+w-2, top, 2, 2); - core.drawImage(ctx, background, 128, 94, 2, 2, left, top+h-2, 2, 2); - core.drawImage(ctx, background, 158, 94, 2, 2, left+w-2, top+h-2, 2, 2); + core.drawImage(ctx, background, 128, 64, 2, 2, left, top, 2, 2); + core.drawImage(ctx, background, 158, 64, 2, 2, left + w - 2, top, 2, 2); + core.drawImage(ctx, background, 128, 94, 2, 2, left, top + h - 2, 2, 2); + core.drawImage(ctx, background, 158, 94, 2, 2, left + w - 2, top + h - 2, 2, 2); // border - core.drawImage(ctx, background, 130, 64, 28, 2, left+2, top, w-4, 2); - core.drawImage(ctx, background, 130, 94, 28, 2, left+2, top+h-2, w-4, 2); - core.drawImage(ctx, background, 128, 66, 2, 28, left, top+2, 2,h-4); - core.drawImage(ctx, background, 158, 66, 2, 28, left+w-2, top+2, 2,h-4); + core.drawImage(ctx, background, 130, 64, 28, 2, left + 2, top, w - 4, 2); + core.drawImage(ctx, background, 130, 94, 28, 2, left + 2, top + h - 2, w - 4, 2); + core.drawImage(ctx, background, 128, 66, 2, 28, left, top + 2, 2, h - 4); + core.drawImage(ctx, background, 158, 66, 2, 28, left + w - 2, top + 2, 2, h - 4); } ////// 绘制 WindowSkin -ui.prototype.drawWindowSkin = function(background, ctx, x, y, w, h, direction, px, py) { +ui.prototype.drawWindowSkin = function (background, ctx, x, y, w, h, direction, px, py) { background = background || core.status.textAttribute.background; - // 仿RM窗口皮肤 ↓ + // 仿RM窗口皮肤 ↓ // 绘制背景 - core.drawImage(ctx, background, 0, 0, 128, 128, x+2, y+2, w-4, h-4); + core.drawImage(ctx, background, 0, 0, 128, 128, x + 2, y + 2, w - 4, h - 4); // 绘制边框 // 上方 - core.drawImage(ctx, background, 128, 0, 16, 16, x, y, 16, 16); + core.drawImage(ctx, background, 128, 0, 16, 16, x, y, 16, 16); for (var dx = 0; dx < w - 64; dx += 32) { - core.drawImage(ctx, background, 144, 0, 32, 16,x+dx+16, y, 32, 16); - core.drawImage(ctx, background, 144,48, 32, 16,x+dx+16, y+h-16, 32, 16); + core.drawImage(ctx, background, 144, 0, 32, 16, x + dx + 16, y, 32, 16); + core.drawImage(ctx, background, 144, 48, 32, 16, x + dx + 16, y + h - 16, 32, 16); } - core.drawImage(ctx, background, 144, 0,w-dx-32, 16,x+dx+16, y,w-dx-32, 16); - core.drawImage(ctx, background, 144,48,w-dx-32, 16,x+dx+16, y+h-16,w-dx-32, 16); - core.drawImage(ctx, background, 176, 0, 16, 16, x+w-16, y, 16, 16); + core.drawImage(ctx, background, 144, 0, w - dx - 32, 16, x + dx + 16, y, w - dx - 32, 16); + core.drawImage(ctx, background, 144, 48, w - dx - 32, 16, x + dx + 16, y + h - 16, w - dx - 32, 16); + core.drawImage(ctx, background, 176, 0, 16, 16, x + w - 16, y, 16, 16); // 左右 for (var dy = 0; dy < h - 64; dy += 32) { - core.drawImage(ctx, background, 128,16, 16, 32, x,y+dy+16, 16, 32); - core.drawImage(ctx, background, 176,16, 16, 32, x+w-16,y+dy+16, 16, 32); + core.drawImage(ctx, background, 128, 16, 16, 32, x, y + dy + 16, 16, 32); + core.drawImage(ctx, background, 176, 16, 16, 32, x + w - 16, y + dy + 16, 16, 32); } - core.drawImage(ctx, background, 128,16, 16,h-dy-32, x,y+dy+16, 16,h-dy-32); - core.drawImage(ctx, background, 176,16, 16,h-dy-32, x+w-16,y+dy+16, 16,h-dy-32); + core.drawImage(ctx, background, 128, 16, 16, h - dy - 32, x, y + dy + 16, 16, h - dy - 32); + core.drawImage(ctx, background, 176, 16, 16, h - dy - 32, x + w - 16, y + dy + 16, 16, h - dy - 32); // 下方 - core.drawImage(ctx, background, 128,48, 16, 16, x, y+h-16, 16, 16); - core.drawImage(ctx, background, 176,48, 16, 16, x+w-16, y+h-16, 16, 16); + core.drawImage(ctx, background, 128, 48, 16, 16, x, y + h - 16, 16, 16); + core.drawImage(ctx, background, 176, 48, 16, 16, x + w - 16, y + h - 16, 16, 16); // arrow - if(px != null && py != null){ - if(direction == 'up'){ - core.drawImage(ctx, background,128,96,32,32,px,y+h-3,32,32); - }else if(direction == 'down') { - core.drawImage(ctx, background,160,96,32,32,px,y-29,32,32); - } + if (px != null && py != null) { + if (direction == 'up') { + core.drawImage(ctx, background, 128, 96, 32, 32, px, y + h - 3, 32, 32); + } else if (direction == 'down') { + core.drawImage(ctx, background, 160, 96, 32, 32, px, y - 29, 32, 32); + } } // 仿RM窗口皮肤 ↑ } @@ -990,7 +991,7 @@ ui.prototype._drawBackground_drawWindowSkin = function (background, left, top, r ctx = ctx || 'ui'; if (typeof background == 'string' && core.material.images.images[background]) { var image = core.material.images.images[background]; - if (image.width==192 && image.height==128) { + if (image.width == 192 && image.height == 128) { core.setAlpha(ctx, this._drawWindowSkin_getOpacity()); this.drawWindowSkin(image, ctx, left, top, right - left, bottom - top, position, px, py); core.setAlpha(ctx, 1); @@ -1040,8 +1041,8 @@ ui.prototype._calTextBoxWidth = function (ctx, content, min_width, max_width, fo // 如果不存在手动换行,尽量调成半行形式 if (allLines.length == 1) { var w = core.calWidth(ctx, allLines[0]) + 10; - if (w= 0 && config.index < content.length) { // --- 当前不应该换行;但是提前检查一下是否是行尾标点 var nextch = content.charAt(config.index); // 确认不是手动换行 - if (nextch != '\n' && !(nextch == '\\' && content.charAt(config.index+1) == 'n')) { + if (nextch != '\n' && !(nextch == '\\' && content.charAt(config.index + 1) == 'n')) { // 检查是否会换行 var nextchwidth = core.calWidth(tempCtx, nextch) + config.letterSpacing; if (config.offsetX + charwidth + nextchwidth > config.maxWidth) { // 下一项会换行,因此在此处换行 this._drawTextContent_newLine(tempCtx, config); - config.index-=ch.length; + config.index -= ch.length; return this._drawTextContent_next(tempCtx, content, config); } } @@ -1255,9 +1256,11 @@ ui.prototype._drawTextContent_drawChar = function (tempCtx, content, config, ch) // 输出 var left = config.offsetX, top = config.offsetY + config.topMargin; core.fillText(tempCtx, ch, left, top); - config.blocks.push({left: config.offsetX, top: config.offsetY, + config.blocks.push({ + left: config.offsetX, top: config.offsetY, width: charwidth, height: config.currfont + config.lineMargin, - line: config.line, marginLeft: 0}); + line: config.line, marginLeft: 0 + }); config.offsetX += charwidth; return true; } @@ -1291,10 +1294,10 @@ ui.prototype._drawTextContent_newLine = function (tempCtx, config) { ui.prototype._drawTextContent_changeColor = function (tempCtx, content, config) { // 检查是不是 [] var index = config.index, index2; - if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { + if (content.charAt(index) == '[' && ((index2 = content.indexOf(']', index)) >= 0)) { // 变色 - var str = content.substring(index+1, index2); - if (str=="") tempCtx.fillStyle = config.color; + var str = content.substring(index + 1, index2); + if (str == "") tempCtx.fillStyle = config.color; else tempCtx.fillStyle = str; config.index = index2 + 1; } @@ -1306,8 +1309,8 @@ ui.prototype._drawTextContent_changeFontSize = function (tempCtx, content, confi config.index++; // 检查是不是 [] var index = config.index, index2; - if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { - var str = content.substring(index+1, index2); + if (content.charAt(index) == '[' && ((index2 = content.indexOf(']', index)) >= 0)) { + var str = content.substring(index + 1, index2); if (!/^\d+$/.test(str)) config.currfont = config.fontSize; else config.currfont = parseInt(str); config.index = index2 + 1; @@ -1322,9 +1325,9 @@ ui.prototype._drawTextContent_changeFont = function (tempCtx, content, config) { config.index++; // 检查是不是 [] var index = config.index, index2; - if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { - var str = content.substring(index+1, index2); - if (str=="") config.font = config.defaultFont; + if (content.charAt(index) == '[' && ((index2 = content.indexOf(']', index)) >= 0)) { + var str = content.substring(index + 1, index2); + if (str == "") config.font = config.defaultFont; else config.font = str; config.index = index2 + 1; } else config.font = config.defaultFont; @@ -1335,8 +1338,8 @@ ui.prototype._drawTextContent_changeFont = function (tempCtx, content, config) { ui.prototype._drawTextContent_emptyChar = function (tempCtx, content, config) { config.index++; var index = config.index, index2; - if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { - var str = content.substring(index+1, index2); + if (content.charAt(index) == '[' && ((index2 = content.indexOf(']', index)) >= 0)) { + var str = content.substring(index + 1, index2); if (/^\d+$/.test(str)) { var value = parseInt(str); for (var i = 0; i < value; ++i) { @@ -1352,8 +1355,8 @@ ui.prototype._drawTextContent_emptyChar = function (tempCtx, content, config) { ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { // 绘制一个 \i 效果 var index = config.index, index2; - if (content.charAt(config.index+1) == '[' && ((index2=content.indexOf(']', index+1))>=0)) { - var str = content.substring(index+2, index2); + if (content.charAt(config.index + 1) == '[' && ((index2 = content.indexOf(']', index + 1)) >= 0)) { + var str = content.substring(index + 2, index2); // --- 获得图标 var iconInfo = core.ui._getDrawableIconInfo(str), image = iconInfo[0], icon = iconInfo[1]; if (image == null) return this._drawTextContent_next(tempCtx, content, config); @@ -1365,11 +1368,13 @@ ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { return this._drawTextContent_next(tempCtx, content, config); } // 绘制到画布上 - core.drawImage(tempCtx, image, 0, 32*icon, 32, 32, left, top, width, width); + core.drawImage(tempCtx, image, 0, 32 * icon, 32, 32, left, top, width, width); - config.blocks.push({left: left, top: config.offsetY, + config.blocks.push({ + left: left, top: config.offsetY, width: width, height: width + config.lineMargin, - line: config.line, marginLeft: 0}); + line: config.line, marginLeft: 0 + }); config.offsetX += width + 6; config.index = index2 + 1; @@ -1416,7 +1421,7 @@ ui.prototype._animateUI = function (type, ctx, callback) { } ////// 绘制一个对话框 ////// -ui.prototype.drawTextBox = function(content, config) { +ui.prototype.drawTextBox = function (content, config) { config = config || {}; this.clearUI(); @@ -1463,7 +1468,7 @@ ui.prototype.drawTextBox = function(content, config) { // Step 5: 绘制正文 var config = this.drawTextContent(config.ctx || 'ui', content, { left: hPos.content_left, top: content_top, maxWidth: hPos.validWidth, - lineHeight: vPos.lineHeight, time: (config.showAll || config.async || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time + lineHeight: vPos.lineHeight, time: (config.showAll || config.async || textAttribute.time <= 0 || core.status.event.id != 'action') ? 0 : textAttribute.time }); // Step 6: 绘制光标 @@ -1484,14 +1489,14 @@ ui.prototype._drawTextBox_drawImages = function (content, ctx) { return content.replace(/(\f|\\f)\[(.*?)]/g, function (text, sympol, str) { var ss = str.split(","); // 绘制 - if (ss.length==3) + if (ss.length == 3) core.drawImage(ctx, ss[0], parseFloat(ss[1]), parseFloat(ss[2])); - else if (ss.length==5) + else if (ss.length == 5) core.drawImage(ctx, ss[0], parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4])); else if (ss.length >= 9) { if (ss.length >= 10) core.setAlpha(ctx, parseFloat(ss[9])); var angle = (parseFloat(ss[10]) || 0) * Math.PI / 180; - core.drawImage(ctx, ss[0], parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4]), + core.drawImage(ctx, ss[0], parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4]), parseFloat(ss[5]), parseFloat(ss[6]), parseFloat(ss[7]), parseFloat(ss[8]), angle); core.setAlpha(ctx, 1); } @@ -1542,7 +1547,7 @@ ui.prototype._drawTextBox_getVerticalPosition = function (content, titleInfo, po }); if (titleInfo.title) height += textAttribute.titlefont + 5; if (titleInfo.icon != null) { - if (titleInfo.title) height = Math.max(height, titleInfo.height+50); + if (titleInfo.title) height = Math.max(height, titleInfo.height + 50); else height = Math.max(height, titleInfo.height + 30); } else if (titleInfo.image) @@ -1553,13 +1558,13 @@ ui.prototype._drawTextBox_getVerticalPosition = function (content, titleInfo, po switch (posInfo.position) { case 'center': top = parseInt((this.PIXEL - height) / 2); break; case 'up': - if (posInfo.px==null || posInfo.py==null) + if (posInfo.px == null || posInfo.py == null) top = 5 + textAttribute.offset; else top = 32 * posInfo.py - height - (titleInfo.height - 32) - yoffset - core.bigmap.offsetY; break; case 'down': - if (posInfo.px==null || posInfo.py==null) + if (posInfo.px == null || posInfo.py == null) top = this.PIXEL - height - 5 - textAttribute.offset; else { top = 32 * posInfo.py + 32 + yoffset - core.bigmap.offsetY; @@ -1597,7 +1602,7 @@ ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, al } if (titleInfo.icon != null) { core.setAlpha(ctx, alpha); - core.strokeRect(ctx, hPos.left + 15 - 1, image_top-1, 34, titleInfo.height + 2, null, 2); + core.strokeRect(ctx, hPos.left + 15 - 1, image_top - 1, 34, titleInfo.height + 2, null, 2); core.setAlpha(ctx, 1); core.status.boxAnimateObjs = []; // --- 勇士 @@ -1615,7 +1620,7 @@ ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, al core.fillRect(ctx, hPos.left + 15, image_top, 32, titleInfo.height, core.material.groundPattern); core.drawImage(ctx, titleInfo.image, 0, 0, core.material.icons.hero.width || 32, core.material.icons.hero.height, hPos.left + 15, image_top, 32, titleInfo.height); - } + } } else { if (titleInfo.bigImage) { @@ -1635,13 +1640,13 @@ ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, al } if (titleInfo.image != null && titleInfo.icon == null) { // 头像图 core.drawImage(ctx, titleInfo.image, 0, 0, titleInfo.image.width, titleInfo.image.height, - hPos.left+10, vPos.top+10, 70, 70); + hPos.left + 10, vPos.top + 10, 70, 70); } return content_top; } ui.prototype._createTextCanvas = function (content, lineHeight) { - var width = this.PIXEL, height = 30 + this.getTextContentHeight(content, {lineHeight: lineHeight}); + var width = this.PIXEL, height = 30 + this.getTextContentHeight(content, { lineHeight: lineHeight }); var ctx = document.createElement('canvas').getContext('2d'); ctx.canvas.width = width; ctx.canvas.height = height; @@ -1668,7 +1673,7 @@ ui.prototype.drawScrollText = function (content, time, lineHeight, callback) { ui.prototype._drawScrollText_animate = function (ctx, time, callback) { // 开始绘制到UI上 time /= Math.max(core.status.replay.speed, 1) - var per_pixel = 1, height = ctx.canvas.height, per_time = time * per_pixel / (this.PIXEL+height); + var per_pixel = 1, height = ctx.canvas.height, per_time = time * per_pixel / (this.PIXEL + height); var currH = this.PIXEL; core.drawImage('ui', ctx.canvas, 0, currH); var animate = setInterval(function () { @@ -1698,10 +1703,10 @@ ui.prototype.textImage = function (content, lineHeight) { } ////// 绘制一个选项界面 ////// -ui.prototype.drawChoices = function(content, choices, width, ctx) { +ui.prototype.drawChoices = function (content, choices, width, ctx) { choices = core.clone(choices || []); - core.status.event.ui = {"text": content, "choices": choices, "width": width}; + core.status.event.ui = { "text": content, "choices": choices, "width": width }; this.clearUI(); content = core.replaceText(content || ""); @@ -1711,7 +1716,7 @@ ui.prototype.drawChoices = function(content, choices, width, ctx) { var vPos = this._drawChoices_getVerticalPosition(titleInfo, choices, hPos); core.status.event.ui.offset = vPos.offset; - var isWindowSkin = this.drawBackground(hPos.left, vPos.top, hPos.right, vPos.bottom, {ctx: ctx}); + var isWindowSkin = this.drawBackground(hPos.left, vPos.top, hPos.right, vPos.bottom, { ctx: ctx }); this._drawChoices_drawTitle(titleInfo, hPos, vPos, ctx); this._drawChoices_drawChoices(choices, isWindowSkin, hPos, vPos, ctx); } @@ -1723,14 +1728,14 @@ ui.prototype._drawChoices_getHorizontalPosition = function (titleInfo, choices, var width = this._calTextBoxWidth(ctx, titleInfo.content || "", width || 246, this.PIXEL - 20); for (var i = 0; i < choices.length; i++) { if (typeof choices[i] === 'string') - choices[i] = {"text": choices[i]}; + choices[i] = { "text": choices[i] }; choices[i].text = core.replaceText(choices[i].text); choices[i].width = core.calWidth(ctx, core.replaceText(choices[i].text)); if (choices[i].icon != null) choices[i].width += 28; - width = Math.max(width, choices[i].width+30); + width = Math.max(width, choices[i].width + 30); } var left = (this.PIXEL - width) / 2, right = left + width; - var content_left = left + (titleInfo.icon == null ? 15: 60), validWidth = right - content_left - 10; + var content_left = left + (titleInfo.icon == null ? 15 : 60), validWidth = right - content_left - 10; return { left: left, right: right, width: width, content_left: content_left, validWidth: validWidth }; } @@ -1754,7 +1759,7 @@ ui.prototype._drawChoices_getVerticalPosition = function (titleInfo, choices, hP choice_top += 32 * offset; } } - return {top: bottom - height, height: height, bottom: bottom, choice_top: choice_top, offset: offset }; + return { top: bottom - height, height: height, bottom: bottom, choice_top: choice_top, offset: offset }; } ui.prototype._drawChoices_drawTitle = function (titleInfo, hPos, vPos, ctx) { @@ -1765,7 +1770,7 @@ ui.prototype._drawChoices_drawTitle = function (titleInfo, hPos, vPos, ctx) { core.setTextAlign(ctx, 'center'); content_top = vPos.top + 41; - var title_offset = hPos.left+hPos.width/2; + var title_offset = hPos.left + hPos.width / 2; // 动画 if (titleInfo.icon != null) { @@ -1813,14 +1818,14 @@ ui.prototype._drawChoices_drawChoices = function (choices, isWindowSkin, hPos, v var iconInfo = this._getDrawableIconInfo(choices[i].icon), image = iconInfo[0], icon = iconInfo[1]; if (image != null) { core.drawImage(ctx, image, 0, 32 * icon, 32, 32, - this.HPIXEL - choices[i].width/2, vPos.choice_top + 32*i - 17, 22, 22); + this.HPIXEL - choices[i].width / 2, vPos.choice_top + 32 * i - 17, 22, 22); offset += 14; } } core.fillText(ctx, choices[i].text, offset, vPos.choice_top + 32 * i, color); } - if (choices.length>0 && core.status.event.selection != 'none') { + if (choices.length > 0 && core.status.event.selection != 'none') { core.status.event.selection = core.status.event.selection || 0; while (core.status.event.selection < 0) core.status.event.selection += choices.length; while (core.status.event.selection >= choices.length) core.status.event.selection -= choices.length; @@ -1828,15 +1833,15 @@ ui.prototype._drawChoices_drawChoices = function (choices, isWindowSkin, hPos, v if (isWindowSkin) { if (hasCtx) { this._drawSelector(ctx, core.status.textAttribute.background, - len + 10, 28, this.HPIXEL - len/2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20); + len + 10, 28, this.HPIXEL - len / 2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20); } else { this._drawWindowSelector(core.status.textAttribute.background, - this.HPIXEL - len/2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20, len + 10, 28); + this.HPIXEL - len / 2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20, len + 10, 28); } } else - core.strokeRoundRect(ctx, this.HPIXEL - len/2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20, - len+10, 28, 6, core.status.globalAttribute.selectColor, 2); + core.strokeRoundRect(ctx, this.HPIXEL - len / 2 - 5, vPos.choice_top + 32 * core.status.event.selection - 20, + len + 10, 28, 6, core.status.globalAttribute.selectColor, 2); } } @@ -1853,7 +1858,7 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback, ctx) { if (core.status.event.id != 'action') { core.status.event.id = 'confirmBox'; core.status.event.ui = text; - core.status.event.data = {'yes': yesCallback, 'no': noCallback}; + core.status.event.data = { 'yes': yesCallback, 'no': noCallback }; } } @@ -1863,30 +1868,30 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback, ctx) { core.setFont(ctx, this._buildFont(19, true)); var contents = text.split("\n"); var rect = this._drawConfirmBox_getRect(contents, ctx); - var isWindowSkin = this.drawBackground(rect.left, rect.top, rect.right, rect.bottom, {ctx: ctx}); + var isWindowSkin = this.drawBackground(rect.left, rect.top, rect.right, rect.bottom, { ctx: ctx }); core.setTextAlign(ctx, 'center'); core.setFillStyle(ctx, core.arrayToRGBA(core.status.textAttribute.text)) for (var i in contents) { - core.fillText(ctx, contents[i], this.HPIXEL, rect.top + 50 + i*30); + core.fillText(ctx, contents[i], this.HPIXEL, rect.top + 50 + i * 30); } core.fillText(ctx, "确定", this.HPIXEL - 38, rect.bottom - 35, null, this._buildFont(17, true)); core.fillText(ctx, "取消", this.HPIXEL + 38, rect.bottom - 35); if (core.status.event.selection != 'none') { - var len=core.calWidth(ctx, "确定"); - var strokeLeft = this.HPIXEL + (76*core.status.event.selection-38) - parseInt(len/2) - 5; - + var len = core.calWidth(ctx, "确定"); + var strokeLeft = this.HPIXEL + (76 * core.status.event.selection - 38) - parseInt(len / 2) - 5; + if (isWindowSkin) { if (hasCtx) { this._drawSelector(ctx, core.status.textAttribute.background, - len + 10, 28, strokeLeft, rect.bottom-35-20); + len + 10, 28, strokeLeft, rect.bottom - 35 - 20); } else { - this._drawWindowSelector(core.status.textAttribute.background, strokeLeft, rect.bottom-35-20, len+10, 28); + this._drawWindowSelector(core.status.textAttribute.background, strokeLeft, rect.bottom - 35 - 20, len + 10, 28); } } else - core.strokeRoundRect(ctx, strokeLeft, rect.bottom-35-20, len+10, 28, 6, core.status.globalAttribute.selectColor, 2); + core.strokeRoundRect(ctx, strokeLeft, rect.bottom - 35 - 20, len + 10, 28, 6, core.status.globalAttribute.selectColor, 2); } } @@ -1895,12 +1900,12 @@ ui.prototype._drawConfirmBox_getRect = function (contents, ctx) { return Math.max(pre, core.calWidth(ctx, curr)); }, 0); var left = Math.min(this.HPIXEL - 40 - parseInt(max_width / 2), 100), right = this.PIXEL - left; - var top = this.HPIXEL - 68 - (contents.length-1)*30, bottom = this.HPIXEL + 68; + var top = this.HPIXEL - 68 - (contents.length - 1) * 30, bottom = this.HPIXEL + 68; return { top: top, left: left, bottom: bottom, right: right, width: right - left, height: bottom - top }; } ////// 绘制等待界面 ////// -ui.prototype.drawWaiting = function(text) { +ui.prototype.drawWaiting = function (text) { core.lockControl(); core.status.event.id = 'waiting'; core.clearUI(); @@ -1914,7 +1919,7 @@ ui.prototype.drawWaiting = function(text) { } ////// 绘制系统设置界面 ////// -ui.prototype._drawSwitchs = function() { +ui.prototype._drawSwitchs = function () { core.status.event.id = 'switchs'; var choices = [ "音效设置", @@ -1946,7 +1951,7 @@ ui.prototype._drawSwitchs_display = function () { "怪物显伤: " + (core.flags.displayEnemyDamage ? "[ON]" : "[OFF]"), "临界显伤: " + (core.flags.displayCritical ? "[ON]" : "[OFF]"), "领域显伤: " + (core.flags.displayExtraDamage ? "[ON]" : "[OFF]"), - "领域模式: " + (core.flags.extraDamageType == 2 ? "[最简]" : core.flags.extraDamageType == 1 ? "[半透明]" : "[完整]" ), + "领域模式: " + (core.flags.extraDamageType == 2 ? "[最简]" : core.flags.extraDamageType == 1 ? "[半透明]" : "[完整]"), "返回上一级", ]; this.drawChoices(null, choices); @@ -1958,9 +1963,9 @@ ui.prototype._drawSwitchs_action = function () { // 数值越大耗时越长 " < 步时:" + core.values.moveSpeed + " > ", " < 转场:" + core.values.floorChangeTime + " > ", - "血瓶绕路: "+(core.hasFlag('__potionNoRouting__') ? "[ON]":"[OFF]"), - "单击瞬移: "+(!core.hasFlag("__noClickMove__") ? "[ON]":"[OFF]"), - "左手模式: "+(core.flags.leftHandPrefer ? "[ON]":"[OFF]"), + "血瓶绕路: " + (core.hasFlag('__potionNoRouting__') ? "[ON]" : "[OFF]"), + "单击瞬移: " + (!core.hasFlag("__noClickMove__") ? "[ON]" : "[OFF]"), + "左手模式: " + (core.flags.leftHandPrefer ? "[ON]" : "[OFF]"), "返回上一级", ]; this.drawChoices(null, choices); @@ -1989,7 +1994,7 @@ ui.prototype._drawQuickShop = function () { core.status.event.id = 'selectShop'; var shopList = core.status.shops, keys = core.listShopIds(); var choices = keys.map(function (shopId) { - return {"text": shopList[shopId].textInList, "color": core.isShopVisited(shopId) ? null : "#999999"}; + return { "text": shopList[shopId].textInList, "color": core.isShopVisited(shopId) ? null : "#999999" }; }); choices.push("返回游戏"); this.drawChoices(null, choices); @@ -2039,7 +2044,7 @@ ui.prototype._drawReplay = function () { ui.prototype._drawGameInfo = function () { core.status.event.id = 'gameInfo'; this.drawChoices(null, [ - "数据统计", "查看工程", "游戏主页", "操作帮助", "关于游戏","下载离线版本", "返回主菜单" + "数据统计", "查看工程", "游戏主页", "操作帮助", "关于游戏", "下载离线版本", "返回主菜单" ]); } @@ -2053,13 +2058,13 @@ ui.prototype.drawPagination = function (page, totalPage, y) { var length = core.calWidth('ui', page + " / " + page, this._buildFont(15, true)); core.setTextAlign('ui', 'left'); - core.fillText('ui', page + " / " + totalPage, parseInt((this.PIXEL - length) / 2), y*32+19); + core.fillText('ui', page + " / " + totalPage, parseInt((this.PIXEL - length) / 2), y * 32 + 19); core.setTextAlign('ui', 'center'); if (page > 1) - core.fillText('ui', '上一页', this.HPIXEL - 80, y*32+19); + core.fillText('ui', '上一页', this.HPIXEL - 80, y * 32 + 19); if (page < totalPage) - core.fillText('ui', '下一页', this.HPIXEL + 80, y*32+19); + core.fillText('ui', '下一页', this.HPIXEL + 80, y * 32 + 19); } ////// 绘制键盘光标 ////// @@ -2075,14 +2080,14 @@ ui.prototype._drawCursor = function () { core.lockControl(); core.clearUI(); var width = 4; - core.strokeRect('ui', 32*automaticRoute.cursorX+width/2, 32*automaticRoute.cursorY+width/2, - 32-width, 32-width, core.status.globalAttribute.selectColor, width); + core.strokeRect('ui', 32 * automaticRoute.cursorX + width / 2, 32 * automaticRoute.cursorY + width / 2, + 32 - width, 32 - width, core.status.globalAttribute.selectColor, width); } ////// 绘制怪物手册 ////// ui.prototype.drawBook = function (index) { - var floorId = core.floorIds[(core.status.event.ui||{}).index] || core.status.floorId; + var floorId = core.floorIds[(core.status.event.ui || {}).index] || core.status.floorId; // 清除浏览地图时的光环缓存 if (floorId != core.status.floorId && core.status.checkBlock) { core.status.checkBlock.cache = {}; @@ -2113,7 +2118,7 @@ ui.prototype.drawBook = function (index) { core.drawBoxAnimate(); this.drawPagination(page, totalPage); core.setTextAlign('ui', 'center'); - core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13,'#DDDDDD', this._buildFont(15, true)); + core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13, '#DDDDDD', this._buildFont(15, true)); } ui.prototype._drawBook_pageinfo = function () { @@ -2136,7 +2141,7 @@ ui.prototype._drawBook_drawBackground = function () { ui.prototype._drawBook_drawEmpty = function () { core.setTextAlign('ui', 'center'); core.fillText('ui', "本层无怪物", this.HPIXEL, this.HPIXEL + 14, '#999999', this._buildFont(50, true)); - core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13,'#DDDDDD', this._buildFont(15, true)); + core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13, '#DDDDDD', this._buildFont(15, true)); } ui.prototype._drawBook_drawOne = function (floorId, index, enemy, pageinfo, selected) { @@ -2177,7 +2182,7 @@ ui.prototype._drawBook_drawBox = function (index, enemy, top, pageinfo) { // 检查大怪物 if (blockInfo.bigImage) { core.status.boxAnimateObjs.push({ - bigImage: blockInfo.bigImage, face: blockInfo.face, centerX: border_left + 21, centerY: border_top + 21, + bigImage: blockInfo.bigImage, face: blockInfo.face, centerX: border_left + 21, centerY: border_top + 21, max_width: 60 }); } @@ -2225,7 +2230,7 @@ ui.prototype._drawBook_drawName = function (index, enemy, top, left, width) { switch (enemy.specialText.length) { case 1: core.fillText('ui', enemy.specialText[0], left + width / 2, - top + 50, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'), + top + 50, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'), this._buildFont(15, true), width); break; case 2: @@ -2238,9 +2243,9 @@ ui.prototype._drawBook_drawName = function (index, enemy, top, left, width) { var rightWidth = core.calWidth('ui', enemy.specialText[1]); // Step 3: 绘制 core.fillText('ui', enemy.specialText[0], left + (width + leftWidth - totalWidth) / 2, - top+50, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A')); + top + 50, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A')); core.fillText('ui', enemy.specialText[1], left + (width + totalWidth - rightWidth) / 2, - top+50, core.arrayToRGBA((enemy.specialColor || [])[1] || '#FF6A6A')); + top + 50, core.arrayToRGBA((enemy.specialColor || [])[1] || '#FF6A6A')); break; default: core.fillText('ui', '多属性...', left + width / 2, @@ -2262,11 +2267,11 @@ ui.prototype._drawBook_drawRow1 = function (index, enemy, top, left, width, posi var b13 = this._buildFont(13, true), f13 = this._buildFont(13, false); var col1 = left, col2 = left + width * 9 / 25, col3 = left + width * 17 / 25; core.fillText('ui', core.getStatusLabel('hp'), col1, position, '#DDDDDD', f13); - core.fillText('ui', core.formatBigNumber(enemy.hp||0), col1 + 30, position, null, b13); + core.fillText('ui', core.formatBigNumber(enemy.hp || 0), col1 + 30, position, null, b13); core.fillText('ui', core.getStatusLabel('atk'), col2, position, null, f13); - core.fillText('ui', core.formatBigNumber(enemy.atk||0), col2 + 30, position, null, b13); + core.fillText('ui', core.formatBigNumber(enemy.atk || 0), col2 + 30, position, null, b13); core.fillText('ui', core.getStatusLabel('def'), col3, position, null, f13); - core.fillText('ui', core.formatBigNumber(enemy.def||0), col3 + 30, position, null, b13); + core.fillText('ui', core.formatBigNumber(enemy.def || 0), col3 + 30, position, null, b13); } ui.prototype._drawBook_drawRow2 = function (index, enemy, top, left, width, position) { @@ -2276,9 +2281,9 @@ ui.prototype._drawBook_drawRow2 = function (index, enemy, top, left, width, posi var col1 = left, col2 = left + width * 9 / 25, col3 = left + width * 17 / 25; // 获得第二行绘制的内容 var second_line = []; - if (core.flags.statusBarItems.indexOf('enableMoney')>=0) second_line.push([core.getStatusLabel('money'), core.formatBigNumber(enemy.money || 0)]); + if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) second_line.push([core.getStatusLabel('money'), core.formatBigNumber(enemy.money || 0)]); if (core.flags.enableAddPoint) second_line.push([core.getStatusLabel('point'), core.formatBigNumber(enemy.point || 0)]); - if (core.flags.statusBarItems.indexOf('enableExp')>=0) second_line.push([core.getStatusLabel('exp'), core.formatBigNumber(enemy.exp || 0)]); + if (core.flags.statusBarItems.indexOf('enableExp') >= 0) second_line.push([core.getStatusLabel('exp'), core.formatBigNumber(enemy.exp || 0)]); var damage_offset = col1 + (this.PIXEL - col1) / 2 - 12; // 第一列 @@ -2305,11 +2310,11 @@ ui.prototype._drawBook_drawRow3 = function (index, enemy, top, left, width, posi var b13 = this._buildFont(13, true), f13 = this._buildFont(13, false); var col1 = left, col2 = left + width * 9 / 25, col3 = left + width * 17 / 25; core.fillText('ui', '临界', col1, position, '#DDDDDD', f13); - core.fillText('ui', core.formatBigNumber(enemy.critical||0), col1 + 30, position, null, b13); + core.fillText('ui', core.formatBigNumber(enemy.critical || 0), col1 + 30, position, null, b13); core.fillText('ui', '减伤', col2, position, null, f13); - core.fillText('ui', core.formatBigNumber(enemy.criticalDamage||0), col2 + 30, position, null, b13); + core.fillText('ui', core.formatBigNumber(enemy.criticalDamage || 0), col2 + 30, position, null, b13); core.fillText('ui', '加防', col3, position, null, f13); - core.fillText('ui', core.formatBigNumber(enemy.defDamage||0), col3 + 30, position, null, b13); + core.fillText('ui', core.formatBigNumber(enemy.defDamage || 0), col3 + 30, position, null, b13); } ui.prototype._drawBook_drawDamage = function (index, enemy, offset, position) { @@ -2343,7 +2348,7 @@ ui.prototype._drawBookDetail = function (index) { var left = 10, width = this.PIXEL - 2 * left, right = left + width; var content_left = left + 25, validWidth = right - content_left - 13; - var height = Math.max(this.getTextContentHeight(content, {fontSize: 16, lineHeight: 24, maxWidth: validWidth}) + 58, 80), + var height = Math.max(this.getTextContentHeight(content, { fontSize: 16, lineHeight: 24, maxWidth: validWidth }) + 58, 80), top = (this.PIXEL - height) / 2, bottom = top + height; core.setAlpha('data', 0.9); @@ -2352,20 +2357,20 @@ ui.prototype._drawBookDetail = function (index) { core.strokeRect('data', left - 1, top - 1, width + 1, height + 1, core.arrayToRGBA(core.status.globalAttribute.borderColor), 2); core.playSound('确定'); - this._drawBookDetail_drawContent(enemy, content, {top: top, content_left: content_left, bottom: bottom, validWidth: validWidth}); + this._drawBookDetail_drawContent(enemy, content, { top: top, content_left: content_left, bottom: bottom, validWidth: validWidth }); } ui.prototype._drawBookDetail_getInfo = function (index) { - var floorId = core.floorIds[(core.status.event.ui||{}).index] || core.status.floorId; + var floorId = core.floorIds[(core.status.event.ui || {}).index] || core.status.floorId; // 清除浏览地图时的光环缓存 if (floorId != core.status.floorId && core.status.checkBlock) { core.status.checkBlock.cache = {}; } var enemys = core.enemys.getCurrentEnemys(floorId); - if (enemys.length==0) return []; + if (enemys.length == 0) return []; index = core.clamp(index, 0, enemys.length - 1); var enemy = enemys[index], enemyId = enemy.id; - var texts=core.enemys.getSpecialHint(enemyId); + var texts = core.enemys.getSpecialHint(enemyId); if (texts.length == 0) texts.push("该怪物无特殊属性。"); if (enemy.description) texts.push(enemy.description + "\r"); texts.push(""); @@ -2409,18 +2414,18 @@ ui.prototype._drawBookDetail_mofang = function (enemy, texts) { if (core.enemys.hasSpecial(enemy.special, 10)) { var hp = enemy.hp; var delta = core.status.hero.atk - core.status.hero.def; - if (delta0) { - texts.push("\r[#FF6A6A]\\d模仿临界计算器:\\d\r[](当前攻防差"+core.formatBigNumber(delta)+")"); + if (delta < hp && hp <= 10000 && hp > 0) { + texts.push("\r[#FF6A6A]\\d模仿临界计算器:\\d\r[](当前攻防差" + core.formatBigNumber(delta) + ")"); var u = []; this._drawBookDetail_mofang_getArray(hp).forEach(function (t) { if (u.length < 20) u.push(t); - else if (Math.abs(t[0]-delta)this.SIZE || data.mh>this.SIZE)) - text+=" ["+(data.x-this.HSIZE)+","+(data.y-this.HSIZE)+"]"; + if (!data.all && (data.mw > this.SIZE || data.mh > this.SIZE)) + text += " [" + (data.x - this.HSIZE) + "," + (data.y - this.HSIZE) + "]"; if (core.markedFloorIds[data.floorId]) - text+=" (已标记)"; + text += " (已标记)"; var textX = 16, textY = 18, width = textX + core.calWidth('data', text) + 16, height = 42; core.fillRect('data', 5, 5, width, height, 'rgba(0,0,0,0.4)'); core.fillText('data', text, textX + 5, textY + 15, 'rgba(255,255,255,0.6)'); @@ -2587,7 +2594,7 @@ ui.prototype._drawViewMaps_drawHint = function () { core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, 'rgba(0,0,0,0.7)'); core.setTextAlign('ui', 'center'); var stroke = function (left, top, width, height, fillStyle, lineWidth) { - core.strokeRect('ui', left+2, top+2, width-4, height-4, fillStyle, lineWidth); + core.strokeRect('ui', left + 2, top + 2, width - 4, height - 4, fillStyle, lineWidth); } var perpx = this.PIXEL / 5, cornerpx = perpx * 3 / 4; @@ -2624,12 +2631,12 @@ ui.prototype._drawViewMaps_drawHint = function () { } ui.prototype._drawViewMaps_buildData = function (index, x, y) { - var damage = (core.status.event.data||{}).damage; - var all = (core.status.event.data||{all: true}).all; - if (index.damage != null) damage=index.damage; - if (index.all != null) all=index.all; - if (index.index != null) { x=index.x; y=index.y; index=index.index; } - index = core.clamp(index, 0, core.floorIds.length-1); + var damage = (core.status.event.data || {}).damage; + var all = (core.status.event.data || { all: true }).all; + if (index.damage != null) damage = index.damage; + if (index.all != null) all = index.all; + if (index.index != null) { x = index.x; y = index.y; index = index.index; } + index = core.clamp(index, 0, core.floorIds.length - 1); if (damage == null) damage = true; // 浏览地图默认开显伤好了 var floorId = core.floorIds[index], mw = core.floors[floorId].width, mh = core.floors[floorId].height; @@ -2638,13 +2645,15 @@ ui.prototype._drawViewMaps_buildData = function (index, x, y) { x = core.clamp(x, this.HSIZE, mw - this.HSIZE - 1); y = core.clamp(y, this.HSIZE, mh - this.HSIZE - 1); - core.status.event.data = {index: index, x: x, y: y, floorId: floorId, mw: mw, mh: mh, - damage: damage, all: all }; + core.status.event.data = { + index: index, x: x, y: y, floorId: floorId, mw: mw, mh: mh, + damage: damage, all: all + }; return core.status.event.data; } ////// 绘制道具栏 ////// -ui.prototype._drawToolbox = function(index) { +ui.prototype._drawToolbox = function (index) { var info = this._drawToolbox_getInfo(index); this._drawToolbox_drawBackground(); @@ -2677,40 +2686,40 @@ ui.prototype.getToolboxItems = function (cls) { return this.uidata.getToolboxItems(cls); } return Object.keys(core.status.hero.items[cls] || {}) - .filter(function (id) { return !core.material.items[id].hideInToolbox; }) - .sort(); + .filter(function (id) { return !core.material.items[id].hideInToolbox; }) + .sort(); } ui.prototype._drawToolbox_getInfo = function (index) { // 设定eventdata if (!core.status.event.data || core.status.event.data.toolsPage == null) - core.status.event.data = {"toolsPage":1, "constantsPage":1, "selectId":null} + core.status.event.data = { "toolsPage": 1, "constantsPage": 1, "selectId": null } // 获取物品列表 - var tools = core.getToolboxItems('tools'), + var tools = core.getToolboxItems('tools'), constants = core.getToolboxItems('constants'); // 处理页数 var toolsPage = core.status.event.data.toolsPage; var constantsPage = core.status.event.data.constantsPage; - var toolsTotalPage = Math.ceil(tools.length/this.LAST); - var constantsTotalPage = Math.ceil(constants.length/this.LAST); + var toolsTotalPage = Math.ceil(tools.length / this.LAST); + var constantsTotalPage = Math.ceil(constants.length / this.LAST); // 处理index if (index == null) index = tools.length == 0 && constants.length > 0 ? this.LAST : 0; - core.status.event.selection=index; + core.status.event.selection = index; // 确认选择对象 var select, selectId; - if (index=tools.length) select=Math.max(0, tools.length-1); + if (index < this.LAST) { + select = index + (toolsPage - 1) * this.LAST; + if (select >= tools.length) select = Math.max(0, tools.length - 1); selectId = tools[select]; } else { - select = index%this.LAST + (constantsPage-1)*this.LAST; - if (select>=constants.length) select=Math.max(0, constants.length-1); + select = index % this.LAST + (constantsPage - 1) * this.LAST; + if (select >= constants.length) select = Math.max(0, constants.length - 1); selectId = constants[select]; } - if (!core.hasItem(selectId)) selectId=null; - core.status.event.data.selectId=selectId; + if (!core.hasItem(selectId)) selectId = null; + core.status.event.data.selectId = selectId; return { index: index, tools: tools, constants: constants, toolsPage: toolsPage, constantsPage: constantsPage, toolsTotalPage: toolsTotalPage, constantsTotalPage: constantsTotalPage, selectId: selectId @@ -2731,23 +2740,23 @@ ui.prototype._drawToolbox_drawLine = function (yoffset, text) { core.canvas.ui.lineTo(this.PIXEL, yoffset); core.canvas.ui.stroke(); core.canvas.ui.beginPath(); - core.canvas.ui.moveTo(this.PIXEL, yoffset-1); - core.canvas.ui.lineTo(this.PIXEL, yoffset-25); - core.canvas.ui.lineTo(this.PIXEL-72, yoffset-25); - core.canvas.ui.lineTo(this.PIXEL-102, yoffset-1); + core.canvas.ui.moveTo(this.PIXEL, yoffset - 1); + core.canvas.ui.lineTo(this.PIXEL, yoffset - 25); + core.canvas.ui.lineTo(this.PIXEL - 72, yoffset - 25); + core.canvas.ui.lineTo(this.PIXEL - 102, yoffset - 1); core.canvas.ui.fill(); - core.fillText('ui', text, this.PIXEL - 5, yoffset-6, '#333333', this._buildFont(16, true)); + core.fillText('ui', text, this.PIXEL - 5, yoffset - 6, '#333333', this._buildFont(16, true)); } ui.prototype._drawToolbox_drawDescription = function (info, max_height) { core.setTextAlign('ui', 'left'); if (!info.selectId) return; - var item=core.material.items[info.selectId]; + var item = core.material.items[info.selectId]; var name = item.name || "未知道具"; - try { name = core.replaceText(name); } catch (e) {} + try { name = core.replaceText(name); } catch (e) { } core.fillText('ui', name, 10, 32, core.status.globalAttribute.selectColor, this._buildFont(20, true)) var text = item.text || "该道具暂无描述。"; - try { text = core.replaceText(text); } catch (e) {} + try { text = core.replaceText(text); } catch (e) { } var height = null; for (var fontSize = 17; fontSize >= 9; fontSize -= 2) { @@ -2779,7 +2788,7 @@ ui.prototype._drawToolbox_drawContent = function (info, line, items, page, drawC } ////// 绘制装备界面 ////// -ui.prototype._drawEquipbox = function(index) { +ui.prototype._drawEquipbox = function (index) { var info = this._drawEquipbox_getInfo(index); this._drawToolbox_drawBackground(); @@ -2806,7 +2815,7 @@ ui.prototype._drawEquipbox = function(index) { ui.prototype._drawEquipbox_getInfo = function (index) { if (!core.status.event.data || core.status.event.data.page == null) - core.status.event.data = {"page":1, "selectId":null}; + core.status.event.data = { "page": 1, "selectId": null }; var allEquips = core.status.globalAttribute.equipName; var equipLength = allEquips.length; if (!core.status.hero.equipment) core.status.hero.equipment = []; @@ -2821,28 +2830,30 @@ ui.prototype._drawEquipbox_getInfo = function (index) { else index = 0; } if (index >= this.LAST && ownEquipment.length == 0) index = 0; - var selectId=null; + var selectId = null; if (index < this.LAST) { - if (index >= equipLength) index=Math.max(0, equipLength - 1); + if (index >= equipLength) index = Math.max(0, equipLength - 1); selectId = equipEquipment[index] || null; } else { - if (page == totalPage) index = Math.min(index, (ownEquipment.length+this.LAST-1)%this.LAST+this.LAST); + if (page == totalPage) index = Math.min(index, (ownEquipment.length + this.LAST - 1) % this.LAST + this.LAST); selectId = ownEquipment[index - this.LAST + (page - 1) * this.LAST]; - if (!core.hasItem(selectId)) selectId=null; + if (!core.hasItem(selectId)) selectId = null; } - core.status.event.selection=index; - core.status.event.data.selectId=selectId; - return { index: index, selectId: selectId, page: page, totalPage: totalPage, allEquips: allEquips, - equipLength: equipLength, equipEquipment: equipEquipment, ownEquipment: ownEquipment}; + core.status.event.selection = index; + core.status.event.data.selectId = selectId; + return { + index: index, selectId: selectId, page: page, totalPage: totalPage, allEquips: allEquips, + equipLength: equipLength, equipEquipment: equipEquipment, ownEquipment: ownEquipment + }; } ui.prototype._drawEquipbox_description = function (info, max_height) { core.setTextAlign('ui', 'left'); if (!info.selectId) return; - var equip=core.material.items[info.selectId]; + var equip = core.material.items[info.selectId]; // --- 标题 - if (!equip.equip) equip.equip = {"type": 0}; + if (!equip.equip) equip.equip = { "type": 0 }; var equipType = equip.equip.type, equipString; if (typeof equipType === 'string') { equipString = equipType || "未知部位"; @@ -2852,7 +2863,7 @@ ui.prototype._drawEquipbox_description = function (info, max_height) { core.fillText('ui', equip.name + "(" + equipString + ")", 10, 32, core.status.globalAttribute.selectColor, this._buildFont(20, true)) // --- 描述 var text = equip.text || "该装备暂无描述。"; - try { text = core.replaceText(text); } catch (e) {} + try { text = core.replaceText(text); } catch (e) { } var height = null; for (var fontSize = 17; fontSize >= 9; fontSize -= 2) { @@ -2897,10 +2908,10 @@ ui.prototype._drawEquipbox_drawStatusChanged = function (info, y, equip, equipTy if (nowValue == newValue) continue; var text = core.getStatusLabel(name); this._drawEquipbox_drawStatusChanged_draw(text + " ", '#CCCCCC', obj); - var color = newValue>nowValue?'#00FF00':'#FF0000'; + var color = newValue > nowValue ? '#00FF00' : '#FF0000'; nowValue = core.formatBigNumber(nowValue); newValue = core.formatBigNumber(newValue); - this._drawEquipbox_drawStatusChanged_draw(nowValue+"->", '#CCCCCC', obj); + this._drawEquipbox_drawStatusChanged_draw(nowValue + "->", '#CCCCCC', obj); this._drawEquipbox_drawStatusChanged_draw(newValue, color, obj); obj.drawOffset += 8; } @@ -2920,7 +2931,7 @@ ui.prototype._drawEquipbox_drawEquiped = function (info, line) { core.setTextAlign('ui', 'center'); var per_line = this.HSIZE - 3, width = Math.floor(this.PIXEL / (per_line + 0.25)); // 当前装备 - for (var i = 0; i < info.equipLength ; i++) { + for (var i = 0; i < info.equipLength; i++) { var equipId = info.equipEquipment[i] || null; // var offset_text = width * (i % per_line) + 56; var offset_image = width * (i % per_line) + width * 2 / 3; @@ -2931,24 +2942,24 @@ ui.prototype._drawEquipbox_drawEquiped = function (info, line) { core.drawImage('ui', core.material.images.items, 0, 32 * icon, 32, 32, offset_image, y, 32, 32); } core.fillText('ui', info.allEquips[i] || "未知", offset_text, y + 27, '#FFFFFF', this._buildFont(16, true)) - core.strokeRoundRect('ui', offset_image - 4, y - 4, 40, 40, 6, info.index==i?core.status.globalAttribute.selectColor:"#FFFFFF"); + core.strokeRoundRect('ui', offset_image - 4, y - 4, 40, 40, 6, info.index == i ? core.status.globalAttribute.selectColor : "#FFFFFF"); } } ////// 绘制存档/读档界面 ////// -ui.prototype._drawSLPanel = function(index, refresh) { +ui.prototype._drawSLPanel = function (index, refresh) { core.control._loadFavoriteSaves(); if (index == null) index = 1; if (index < 0) index = 0; - var page = parseInt(index/10), offset=index%10; + var page = parseInt(index / 10), offset = index % 10; var max_page = main.savePages || 30; - if(core.status.event.data && core.status.event.data.mode=='fav') - max_page = Math.ceil((core.saves.favorite||[]).length/5); - if (page>=max_page) page=max_page - 1; - if (offset>5) offset=5; - if (core.status.event.data && core.status.event.data.mode=='fav' && page == max_page - 1) { - offset = Math.min(offset, (core.saves.favorite||[]).length - 5 * page); + if (core.status.event.data && core.status.event.data.mode == 'fav') + max_page = Math.ceil((core.saves.favorite || []).length / 5); + if (page >= max_page) page = max_page - 1; + if (offset > 5) offset = 5; + if (core.status.event.data && core.status.event.data.mode == 'fav' && page == max_page - 1) { + offset = Math.min(offset, (core.saves.favorite || []).length - 5 * page); } var last_page = -1; @@ -2957,7 +2968,7 @@ ui.prototype._drawSLPanel = function(index, refresh) { last_page = core.status.event.data.page; mode = core.status.event.data.mode; } - core.status.event.data={ 'page':page, 'offset':offset, 'mode':mode }; + core.status.event.data = { 'page': page, 'offset': offset, 'mode': mode }; core.status.event.ui = core.status.event.ui || []; if (refresh || page != last_page) { core.status.event.ui = []; @@ -2972,19 +2983,19 @@ ui.prototype._drawSLPanel_draw = function (page, max_page) { // --- 绘制背景 this._drawSLPanel_drawBackground(); // --- 绘制文字 - core.ui.drawPagination(page+1, max_page); + core.ui.drawPagination(page + 1, max_page); core.setTextAlign('ui', 'center'); - var bottom = this.PIXEL-13; - core.fillText('ui', '返回游戏', this.PIXEL-48, bottom, '#DDDDDD', this._buildFont(15, true)); + var bottom = this.PIXEL - 13; + core.fillText('ui', '返回游戏', this.PIXEL - 48, bottom, '#DDDDDD', this._buildFont(15, true)); if (core.status.event.selection) core.setFillStyle('ui', '#FF6A6A'); - if (core.status.event.id=='save') + if (core.status.event.id == 'save') core.fillText('ui', '删除模式', 48, bottom); - else{ - if(core.status.event.data.mode=='all'){ + else { + if (core.status.event.data.mode == 'all') { core.fillText('ui', '[E]显示收藏', 52, bottom); - }else{ + } else { core.fillText('ui', '[E]显示全部', 52, bottom); } } @@ -2992,105 +3003,105 @@ ui.prototype._drawSLPanel_draw = function (page, max_page) { this._drawSLPanel_drawRecords(); } -ui.prototype._drawSLPanel_drawBackground = function() { +ui.prototype._drawSLPanel_drawBackground = function () { core.clearMap('ui'); core.setAlpha('ui', 0.85); core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, '#000000');//可改成背景图图 core.setAlpha('ui', 1); } -ui.prototype._drawSLPanel_loadSave = function(page, callback) { +ui.prototype._drawSLPanel_loadSave = function (page, callback) { var ids = [0]; for (var i = 1; i <= 5; ++i) { var id = 5 * page + i; - if(core.status.event.data.mode=='fav') + if (core.status.event.data.mode == 'fav') id = core.saves.favorite[id - 1]; // 因为favorite第一个不是自动存档 所以要偏移1 ids.push(id); } core.getSaves(ids, function (data) { for (var i = 1; i < ids.length; ++i) core.status.event.ui[i] = data[i]; - core.status.event.ui[0] = data[0] == null ? null : data[0][core.saves.autosave.now-1]; + core.status.event.ui[0] = data[0] == null ? null : data[0][core.saves.autosave.now - 1]; callback(); }); } // 在以x为中心轴 y为顶坐标 的位置绘制一条宽为size的记录 cho表示是否被选中 选中会加粗 highlight表示高亮标题 ✐ -ui.prototype._drawSLPanel_drawRecord = function(title, data, x, y, size, cho, highLight){ +ui.prototype._drawSLPanel_drawRecord = function (title, data, x, y, size, cho, highLight) { var globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute; var strokeColor = globalAttribute.selectColor; if (core.status.event.selection) strokeColor = '#FF6A6A'; if (!data || !data.floorId) highLight = false; if (data && data.__toReplay__) title = '[R]' + title; - core.fillText('ui', title, x, y, highLight?globalAttribute.selectColor:'#FFFFFF', this._buildFont(17, true)); - core.strokeRect('ui', x-size/2, y+15, size, size, cho?strokeColor:'#FFFFFF', cho?6:2); + core.fillText('ui', title, x, y, highLight ? globalAttribute.selectColor : '#FFFFFF', this._buildFont(17, true)); + core.strokeRect('ui', x - size / 2, y + 15, size, size, cho ? strokeColor : '#FFFFFF', cho ? 6 : 2); if (data && data.floorId) { core.setTextAlign('ui', "center"); var map = core.maps.loadMap(data.maps, data.floorId); core.extractBlocksForUI(map, data.hero.flags); core.drawThumbnail(data.floorId, map.blocks, { heroLoc: data.hero.loc, heroIcon: data.hero.image, flags: data.hero.flags, - ctx: 'ui', x: x-size/2, y: y+15, size: size, centerX: data.hero.loc.x, centerY: data.hero.loc.y + ctx: 'ui', x: x - size / 2, y: y + 15, size: size, centerX: data.hero.loc.x, centerY: data.hero.loc.y }); if (core.isPlaying() && core.getFlag("hard") != data.hero.flags.hard) { - core.fillRect('ui', x-size/2, y+15, size, size, [0, 0, 0, 0.4]); - core.fillText('ui', data.hard, x, parseInt(y+22+size/2), data.hero.flags.__hardColor__ || 'red', this._buildFont(30,true)); + core.fillRect('ui', x - size / 2, y + 15, size, size, [0, 0, 0, 0.4]); + core.fillText('ui', data.hard, x, parseInt(y + 22 + size / 2), data.hero.flags.__hardColor__ || 'red', this._buildFont(30, true)); } // 绘制存档笔记 if (data.hero.notes && data.hero.notes.length > 0) { core.setTextAlign('ui', 'left'); if (data.hero.notes.length >= 2) { - core.fillRect('ui', x-size/2, y + 15, size, 28, [0,0,0,0.3]); - core.fillBoldText('ui', data.hero.notes.length - 1 + ". " + data.hero.notes[data.hero.notes.length - 2].substring(0, 10), + core.fillRect('ui', x - size / 2, y + 15, size, 28, [0, 0, 0, 0.3]); + core.fillBoldText('ui', data.hero.notes.length - 1 + ". " + data.hero.notes[data.hero.notes.length - 2].substring(0, 10), x - size / 2 + 2, y + 15 + 12, '#FFFFFF', null, this._buildFont(10, false)); - core.fillBoldText('ui', data.hero.notes.length + ". " + data.hero.notes[data.hero.notes.length - 1].substring(0, 10), + core.fillBoldText('ui', data.hero.notes.length + ". " + data.hero.notes[data.hero.notes.length - 1].substring(0, 10), x - size / 2 + 2, y + 15 + 24); } else { - core.fillRect('ui', x-size/2, y + 15, size, 16, [0,0,0,0.3]); - core.fillBoldText('ui', data.hero.notes.length + ". " + data.hero.notes[data.hero.notes.length - 1].substring(0, 10), + core.fillRect('ui', x - size / 2, y + 15, size, 16, [0, 0, 0, 0.3]); + core.fillBoldText('ui', data.hero.notes.length + ". " + data.hero.notes[data.hero.notes.length - 1].substring(0, 10), x - size / 2 + 2, y + 15 + 12, '#FFFFFF', null, this._buildFont(10, false)); } } core.setTextAlign('ui', "center"); - var v = core.formatBigNumber(data.hero.hp,true)+"/"+core.formatBigNumber(data.hero.atk,true)+"/"+core.formatBigNumber(data.hero.def,true); - var v2 = "/"+core.formatBigNumber(data.hero.mdef,true); + var v = core.formatBigNumber(data.hero.hp, true) + "/" + core.formatBigNumber(data.hero.atk, true) + "/" + core.formatBigNumber(data.hero.def, true); + var v2 = "/" + core.formatBigNumber(data.hero.mdef, true); if (core.calWidth('ui', v + v2, this._buildFont(10, false)) <= size) v += v2; - core.fillText('ui', v, x, y+30+size, globalAttribute.selectColor); - core.fillText('ui', core.formatDate(new Date(data.time)), x, y+43+size, data.hero.flags.debug?'#FF6A6A':'#FFFFFF'); + core.fillText('ui', v, x, y + 30 + size, globalAttribute.selectColor); + core.fillText('ui', core.formatDate(new Date(data.time)), x, y + 43 + size, data.hero.flags.debug ? '#FF6A6A' : '#FFFFFF'); } else { - core.fillRect('ui', x-size/2, y+15, size, size, '#333333'); - core.fillText('ui', '空', x, parseInt(y+22+size/2), '#FFFFFF', this._buildFont(30, true)); - } + core.fillRect('ui', x - size / 2, y + 15, size, size, '#333333'); + core.fillText('ui', '空', x, parseInt(y + 22 + size / 2), '#FFFFFF', this._buildFont(30, true)); + } } -ui.prototype._drawSLPanel_drawRecords = function (n) { +ui.prototype._drawSLPanel_drawRecords = function (n) { var page = core.status.event.data.page; var offset = core.status.event.data.offset; - var u = Math.floor(this.PIXEL/6), size = Math.floor(this.PIXEL/3-20); - var name=core.status.event.id=='save'?"存档":core.status.event.id=='load'?"读档":"回放"; + var u = Math.floor(this.PIXEL / 6), size = Math.floor(this.PIXEL / 3 - 20); + var name = core.status.event.id == 'save' ? "存档" : core.status.event.id == 'load' ? "读档" : "回放"; - for (var i = 0; i < (n||6); i++){ + for (var i = 0; i < (n || 6); i++) { var data = core.status.event.ui[i]; var id = 5 * page + i; - var highLight = (i>0&&core.saves.favorite.indexOf(id)>=0) || core.status.event.data.mode=='fav'; - var title = (highLight?'★ ':'☆ ') + (core.saves.favoriteName[id] || (name + id)); - if (i != 0 && core.status.event.data.mode=='fav') { + var highLight = (i > 0 && core.saves.favorite.indexOf(id) >= 0) || core.status.event.data.mode == 'fav'; + var title = (highLight ? '★ ' : '☆ ') + (core.saves.favoriteName[id] || (name + id)); + if (i != 0 && core.status.event.data.mode == 'fav') { if (!data) break; var real_id = core.saves.favorite[id - 1]; title = (core.saves.favoriteName[real_id] || (name + real_id)) + ' ✐'; } var charSize = 32;// 字体占用像素范围 - var topSpan = parseInt((this.PIXEL-charSize-2*(charSize*2 + size))/3);// Margin - var yTop1 = topSpan+parseInt(charSize/2) + 8;//文字的中心 - var yTop2 = yTop1+charSize*2+size+topSpan; - if (i<3) { - this._drawSLPanel_drawRecord(i==0?"自动存档":title, data, (2*i+1)*u, yTop1, size, i==offset, highLight); + var topSpan = parseInt((this.PIXEL - charSize - 2 * (charSize * 2 + size)) / 3);// Margin + var yTop1 = topSpan + parseInt(charSize / 2) + 8;//文字的中心 + var yTop2 = yTop1 + charSize * 2 + size + topSpan; + if (i < 3) { + this._drawSLPanel_drawRecord(i == 0 ? "自动存档" : title, data, (2 * i + 1) * u, yTop1, size, i == offset, highLight); } else { - this._drawSLPanel_drawRecord(title, data, (2*i-5)*u, yTop2, size, i==offset, highLight); + this._drawSLPanel_drawRecord(title, data, (2 * i - 5) * u, yTop2, size, i == offset, highLight); } } }; @@ -3117,23 +3128,23 @@ ui.prototype._drawKeyBoard = function () { var now = this.HPIXEL - 89 + offset; var lines = [ - ["F1","F2","F3","F4","F5","F6","F7","F8","F9","10","11"], - ["1","2","3","4","5","6","7","8","9","0"], - ["Q","W","E","R","T","Y","U","I","O","P"], - ["A","S","D","F","G","H","J","K","L"], - ["Z","X","C","V","B","N","M"], - ["-","=","[","]","\\",";","'",",",".","/","`"], - ["ES","TA","CA","SH","CT","AL","SP","BS","EN","DE"] + ["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "10", "11"], + ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], + ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"], + ["A", "S", "D", "F", "G", "H", "J", "K", "L"], + ["Z", "X", "C", "V", "B", "N", "M"], + ["-", "=", "[", "]", "\\", ";", "'", ",", ".", "/", "`"], + ["ES", "TA", "CA", "SH", "CT", "AL", "SP", "BS", "EN", "DE"] ]; lines.forEach(function (line) { - for (var i=0;i=0?(",中毒伤害"+core.formatBigNumber(statistics.poisonDamage)+"点"):"") - +",领域/夹击/阻击/血网伤害"+core.formatBigNumber(statistics.extraDamage)+"点。", + "当前总步数:" + core.status.hero.steps + ",当前游戏时长:" + core.formatTime(statistics.currTime) + + ",总游戏时长" + core.formatTime(statistics.totalTime) + + "。\n瞬间移动次数:" + statistics.moveDirectly + ",共计少走" + statistics.ignoreSteps + "步。" + + "\n\n总计通过血瓶恢复生命值为" + core.formatBigNumber(statistics.hp) + "点。\n\n" + + "总计打死了" + statistics.battle + "个怪物,得到了" + core.formatBigNumber(statistics.money) + "金币," + core.formatBigNumber(statistics.exp) + "点经验。\n\n" + + "受到的总伤害为" + core.formatBigNumber(statistics.battleDamage + statistics.poisonDamage + statistics.extraDamage) + + ",其中战斗伤害" + core.formatBigNumber(statistics.battleDamage) + "点" + + (core.flags.statusBarItems.indexOf('enableDebuff') >= 0 ? (",中毒伤害" + core.formatBigNumber(statistics.poisonDamage) + "点") : "") + + ",领域/夹击/阻击/血网伤害" + core.formatBigNumber(statistics.extraDamage) + "点。", "\t[说明]1. 地图数据统计的效果仅模拟当前立刻获得该道具的效果。\n2. 不会计算“不可被浏览地图”的隐藏层的数据。\n" + - "3. 不会计算任何通过事件得到的道具(显示事件、改变图块、或直接增加道具等)。\n"+ - "4. 在自定义道具(例如其他宝石)后,需在脚本编辑的drawStatistics中注册,不然不会进行统计。\n"+ + "3. 不会计算任何通过事件得到的道具(显示事件、改变图块、或直接增加道具等)。\n" + + "4. 在自定义道具(例如其他宝石)后,需在脚本编辑的drawStatistics中注册,不然不会进行统计。\n" + "5. 道具不会统计通过插入事件或useItemEvent实现的效果。\n6. 所有统计信息仅供参考,如有错误,概不负责。" ]) core.removeFlag("__replayText__"); @@ -3198,8 +3209,8 @@ ui.prototype._drawStatistics_buildObj = function () { var order = ["doors", "items", "tools", "constants", "equips"]; ids.sort(function (a, b) { var c1 = order.indexOf(cls[a]), c2 = order.indexOf(cls[b]); - if (c1==c2) return ori.indexOf(a)-ori.indexOf(b); - return c1-c2; + if (c1 == c2) return ori.indexOf(a) - ori.indexOf(b); + return c1 - c2; }); var obj = { 'monster': { @@ -3210,7 +3221,7 @@ ui.prototype._drawStatistics_buildObj = function () { 'hp': 0, 'atk': 0, 'def': 0, 'mdef': 0 } }; - return {ids: ids, cls: cls, ext: ext, total: core.clone(obj), current: core.clone(obj), marked: core.clone(obj)}; + return { ids: ids, cls: cls, ext: ext, total: core.clone(obj), current: core.clone(obj), marked: core.clone(obj) }; } ui.prototype._drawStatistics_add = function (floorId, obj, x1, x2, value) { @@ -3225,11 +3236,11 @@ ui.prototype._drawStatistics_floorId = function (floorId, obj) { core.extractBlocks(floorId); var floor = core.status.maps[floorId], blocks = floor.blocks; // 隐藏层不给看 - if (floor.cannotViewMap && floorId!=core.status.floorId) return; + if (floor.cannotViewMap && floorId != core.status.floorId) return; blocks.forEach(function (block) { if (block.disable) return; var event = block.event; - if (event.cls.indexOf("enemy")==0) { + if (event.cls.indexOf("enemy") == 0) { core.ui._drawStatistics_enemy(floorId, event.id, obj); } else { @@ -3249,14 +3260,14 @@ ui.prototype._drawStatistics_enemy = function (floorId, id, obj) { } ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { - var hp=0, atk=0, def=0, mdef=0; - if (obj.cls[id]=='items' && id!='superPotion') { + var hp = 0, atk = 0, def = 0, mdef = 0; + if (obj.cls[id] == 'items' && id != 'superPotion') { var temp = core.clone(core.status.hero); core.setFlag("__statistics__", true); var ratio = core.status.thisMap.ratio; core.status.thisMap.ratio = core.clone(core.status.maps[floorId].ratio); try { eval(core.material.items[id].itemEffect); } - catch (e) {} + catch (e) { } core.status.thisMap.ratio = ratio; hp = core.status.hero.hp - temp.hp; atk = core.status.hero.atk - temp.atk; @@ -3266,13 +3277,13 @@ ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { window.hero = core.status.hero; window.flags = core.status.hero.flags; } - else if (obj.cls[id]=='equips') { + else if (obj.cls[id] == 'equips') { var values = core.material.items[id].equip || {}; atk = values.atk || 0; def = values.def || 0; mdef = values.mdef || 0; } - if (id.indexOf('sword')==0 || id.indexOf('shield')==0 || obj.cls[id]=='equips') { + if (id.indexOf('sword') == 0 || id.indexOf('shield') == 0 || obj.cls[id] == 'equips') { var t = ""; if (atk > 0) t += atk + core.getStatusLabel('atk'); if (def > 0) t += def + core.getStatusLabel('def'); @@ -3287,35 +3298,35 @@ ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { } ui.prototype._drawStatistics_generateText = function (obj, type, data) { - var text = type+"地图中:\n"; - text += "共有怪物"+data.monster.count+"个"; - if (core.flags.statusBarItems.indexOf('enableMoney')>=0) text+=",总金币数"+data.monster.money; - if (core.flags.statusBarItems.indexOf('enableExp')>=0) text+=",总经验数"+data.monster.exp; - if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point; - text+="。\n"; + var text = type + "地图中:\n"; + text += "共有怪物" + data.monster.count + "个"; + if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) text += ",总金币数" + data.monster.money; + if (core.flags.statusBarItems.indexOf('enableExp') >= 0) text += ",总经验数" + data.monster.exp; + if (core.flags.enableAddPoint) text += ",总加点数" + data.monster.point; + text += "。\n"; var prev = ""; obj.ids.forEach(function (key) { var value = data.count[key]; - if (value==0) return; + if (value == 0) return; if (obj.cls[key] != prev) { if (prev != "") text += "。"; text += "\n"; } else text += ","; prev = obj.cls[key]; - var name = ((core.material.items[key] || (core.getBlockById(key) || {}).event)||{}).name || key; - text+=name+value+"个"; + var name = ((core.material.items[key] || (core.getBlockById(key) || {}).event) || {}).name || key; + text += name + value + "个"; if (obj.ext[key]) - text+="("+obj.ext[key]+")"; + text += "(" + obj.ext[key] + ")"; }) - if (prev!="") text+="。"; + if (prev != "") text += "。"; - text+="\n"; - text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击" - +core.formatBigNumber(data.add.atk)+"点,防御" - +core.formatBigNumber(data.add.def)+"点,护盾" - +core.formatBigNumber(data.add.mdef)+"点。"; + text += "\n"; + text += "共加生命值" + core.formatBigNumber(data.add.hp) + "点,攻击" + + core.formatBigNumber(data.add.atk) + "点,防御" + + core.formatBigNumber(data.add.def) + "点,护盾" + + core.formatBigNumber(data.add.mdef) + "点。"; return text; } @@ -3337,10 +3348,10 @@ ui.prototype._drawHelp = function () { } else { core.drawText([ - "\t[键盘快捷键列表]"+ + "\t[键盘快捷键列表]" + "[CTRL] 跳过对话 [Z] 转向\n" + - "[X] "+core.material.items['book'].name + " [G] "+core.material.items['fly'].name+"\n" + - "[A] 读取自动存档 [W] 撤销读取自动存档\n" + + "[X] " + core.material.items['book'].name + " [G] " + core.material.items['fly'].name + "\n" + + "[A] 读取自动存档 [W] 撤销读取自动存档\n" + "[S/D] 存读档页面 [SPACE] 轻按\n" + "[V] 快捷商店 [ESC] 系统菜单\n" + "[T] 道具页面 [Q] 装备页面\n" + @@ -3348,16 +3359,16 @@ ui.prototype._drawHelp = function () { "[R] 回放录像 [E] 显示光标\n" + "[N] 返回标题页面 [P] 游戏主页\n" + "[O] 查看工程 [F7] 打开debug穿墙模式\n" + - "[PgUp/PgDn] 浏览地图\n"+ - "[1~4] 快捷使用破炸飞和其他道具\n"+ + "[PgUp/PgDn] 浏览地图\n" + + "[1~4] 快捷使用破炸飞和其他道具\n" + "[Alt+0~9] 快捷换装", - "\t[鼠标操作]"+ - "点状态栏中图标: 进行对应的操作\n"+ - "点任意块: 寻路并移动\n"+ - "点任意块并拖动: 指定寻路路线\n"+ - "双击空地: 瞬间移动\n"+ - "单击勇士: 转向\n"+ - "双击勇士: 轻按(仅在轻按开关打开时有效)\n"+ + "\t[鼠标操作]" + + "点状态栏中图标: 进行对应的操作\n" + + "点任意块: 寻路并移动\n" + + "点任意块并拖动: 指定寻路路线\n" + + "双击空地: 瞬间移动\n" + + "单击勇士: 转向\n" + + "双击勇士: 轻按(仅在轻按开关打开时有效)\n" + "长按任意位置:跳过剧情对话或打开虚拟键盘" ]); } @@ -3431,7 +3442,7 @@ ui.prototype.rotateCanvas = function (name, angle, centerX, centerY) { if (angle == 0) { canvas.style.transform = ''; } else { - canvas.style.transform = 'rotate(' + angle +'deg)'; + canvas.style.transform = 'rotate(' + angle + 'deg)'; } canvas.setAttribute('_angle', angle); } diff --git a/project/functions.js b/project/functions.js index a05e80b7..4021e500 100644 --- a/project/functions.js +++ b/project/functions.js @@ -1,1738 +1,1738 @@ -var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = +var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { - "events": { - "resetGame": function (hero, hard, floorId, maps, values) { - // 重置整个游戏;此函数将在游戏开始时,或者每次读档时最先被调用 - // hero:勇士信息;hard:难度;floorId:当前楼层ID;maps:地图信息;values:全局数值信息 + "events": { + "resetGame": function (hero, hard, floorId, maps, values) { + // 重置整个游戏;此函数将在游戏开始时,或者每次读档时最先被调用 + // hero:勇士信息;hard:难度;floorId:当前楼层ID;maps:地图信息;values:全局数值信息 - // 清除游戏数据 - // 这一步会清空状态栏和全部画布内容,并删除所有动态创建的画布 - core.clearStatus(); - // 初始化status - core.status = core.clone(core.initStatus, function (name) { - return name != 'hero' && name != 'maps'; - }); - core.control._bindRoutePush(); - core.status.played = true; - // 初始化人物,图标,统计信息 - core.status.hero = core.clone(hero); - window.hero = core.status.hero; - window.flags = core.status.hero.flags; - core.events.setHeroIcon(core.status.hero.image, true); - core.control._initStatistics(core.animateFrame.totalTime); - core.status.hero.statistics.totalTime = core.animateFrame.totalTime = - Math.max(core.status.hero.statistics.totalTime, core.animateFrame.totalTime); - core.status.hero.statistics.start = null; - // 初始难度 - core.status.hard = hard || ""; - // 初始化地图 - core.status.floorId = floorId; - core.status.maps = maps; - core.maps._resetFloorImages(); - // 初始化怪物和道具 - core.material.enemys = core.enemys.getEnemys(); - core.material.items = core.items.getItems(); - // 初始化全局数值和全局开关 - core.values = core.clone(core.data.values); - for (var key in values || {}) - core.values[key] = values[key]; - core.flags = core.clone(core.data.flags); - var globalFlags = core.getFlag("globalFlags", {}); - for (var key in globalFlags) - core.flags[key] = globalFlags[key]; - core._init_sys_flags(); - // 初始化界面,状态栏等 - core.resize(); - // 状态栏是否显示 - if (core.hasFlag('hideStatusBar')) - core.hideStatusBar(core.hasFlag('showToolbox')); - else - core.showStatusBar(); - // 隐藏右下角的音乐按钮 - core.dom.musicBtn.style.display = 'none'; - core.dom.enlargeBtn.style.display = 'none'; -}, - "win": function (reason, norank, noexit) { - // 游戏获胜事件 - // 请注意,成绩统计时是按照hp进行上传并排名 - // 可以先在这里对最终分数进行计算,比如将2倍攻击和5倍黄钥匙数量加到分数上 - // core.status.hero.hp += 2 * core.getRealStatus('atk') + 5 * core.itemCount('yellowKey'); - - // 如果不退出,则临时存储数据 - if (noexit) { - core.status.extraEvent = core.clone(core.status.event); - } - - // 游戏获胜事件 - core.ui.closePanel(); - var replaying = core.isReplaying(); - if (replaying) core.stopReplay(); - core.waitHeroToStop(function () { - if (!noexit) { - core.clearMap('all'); // 清空全地图 - core.deleteAllCanvas(); // 删除所有创建的画布 - core.dom.gif2.innerHTML = ""; - } - reason = core.replaceText(reason); - core.drawText([ - "\t[" + (reason || "恭喜通关") + "]你的分数是${status:hp}。" - ], function () { - core.events.gameOver(reason || '', replaying, norank); - }) - }); -}, - "lose": function (reason) { - // 游戏失败事件 - core.ui.closePanel(); - var replaying = core.isReplaying(); - core.stopReplay(); - core.waitHeroToStop(function () { - core.drawText([ - "\t[" + (reason || "结局1") + "]你死了。\n如题。" - ], function () { - core.events.gameOver(null, replaying); - }); - }) -}, - "changingFloor": function (floorId, heroLoc) { - // 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻 - // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置 - - // ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- // - var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null - var fromLoad = core.hasFlag('__fromLoad__'); // 是否是读档造成的切换 - var isFlying = core.hasFlag('__isFlying__'); // 是否是楼传造成的切换 - if (!fromLoad && !(isFlying && currentId == floorId)) { - if (!core.hasFlag("__leaveLoc__")) core.setFlag("__leaveLoc__", {}); - if (currentId != null) core.getFlag("__leaveLoc__")[currentId] = core.clone(core.status.hero.loc); - } - - // 可以对currentId进行判定,比如删除某些自定义图层等 - // if (currentId == 'MT0') { - // core.deleteAllCanvas(); - // } - - // 根据分区信息自动砍层与恢复 - if (core.autoRemoveMaps) core.autoRemoveMaps(floorId); - - // 重置画布尺寸 - core.maps.resizeMap(floorId); - // 设置勇士的位置 - heroLoc.direction = core.turnDirection(heroLoc.direction); - core.status.hero.loc = heroLoc; - // 检查重生怪并重置 - if (!fromLoad) { - core.extractBlocks(floorId); - core.status.maps[floorId].blocks.forEach(function (block) { - if (block.disable && core.enemys.hasSpecial(block.event.id, 23)) { - block.disable = false; - core.setMapBlockDisabled(floorId, block.x, block.y, false); - core.maps._updateMapArray(floorId, block.x, block.y); - } - }); - core.control.gatherFollowers(); - } - - // ---------- 重绘新地图;这一步将会设置core.status.floorId ---------- // - core.drawMap(floorId); - - // 切换楼层BGM - if (core.status.maps[floorId].bgm) { - var bgm = core.status.maps[floorId].bgm; - if (bgm instanceof Array) bgm = bgm[Math.floor(Math.random() * bgm.length)]; // 多个bgm则随机播放一个 - if (!core.hasFlag("__bgm__")) core.playBgm(bgm); - } else if (fromLoad && !core.hasFlag("__bgm__")) { - core.pauseBgm(); - } - // 更改画面色调 - var color = core.getFlag('__color__', null); - if (!color && core.status.maps[floorId].color) - color = core.status.maps[floorId].color; - core.clearMap('curtain'); - core.status.curtainColor = color; - if (color) core.fillRect('curtain', 0, 0, core.__PIXELS__, core.__PIXELS__, core.arrayToRGBA(color)); - // 更改天气 - var weather = core.getFlag('__weather__', null); - if (!weather && core.status.maps[floorId].weather) - weather = core.status.maps[floorId].weather; - if (weather) - core.setWeather(weather[0], weather[1]); - else core.setWeather(); - - // ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等 - -}, - "afterChangeFloor": function (floorId) { - // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 - // floorId是切换到的楼层 - - // 如果是读档,则进行检查(是否需要恢复事件) - if (core.hasFlag('__fromLoad__')) { - core.events.recoverEvents(core.getFlag("__events__")); - core.removeFlag("__events__"); - } else { - // 每次抵达楼层执行的事件 - core.insertAction(core.floors[floorId].eachArrive); - - // 首次抵达楼层时执行的事件(后插入,先执行) - if (!core.hasVisitedFloor(floorId)) { - core.insertAction(core.floors[floorId].firstArrive); - core.visitFloor(floorId); - } - } -}, - "flyTo": function (toId, callback) { - // 楼层传送器的使用,从当前楼层飞往toId - // 如果不能飞行请返回false - - var fromId = core.status.floorId; - - // 检查能否飞行 - if (!core.status.maps[fromId].canFlyFrom || !core.status.maps[toId].canFlyTo || !core.hasVisitedFloor(toId)) { - core.playSound('操作失败'); - core.drawTip("无法飞往" + core.status.maps[toId].title + "!", 'fly'); - return false; - } - - // 平面塔模式 - var stair = null, - loc = null; - if (core.flags.flyRecordPosition) { - loc = core.getFlag("__leaveLoc__", {})[toId] || null; - } - if (core.status.maps[toId].flyPoint != null && core.status.maps[toId].flyPoint.length == 2) { - stair = 'flyPoint'; - } - if (stair == null && loc == null) { - // 获得两个楼层的索引,以决定是上楼梯还是下楼梯 - var fromIndex = core.floorIds.indexOf(fromId), - toIndex = core.floorIds.indexOf(toId); - var stair = fromIndex <= toIndex ? "downFloor" : "upFloor"; - // 地下层:同层传送至上楼梯 - if (fromIndex == toIndex && core.status.maps[fromId].underGround) stair = "upFloor"; - } - - // 记录录像 - core.status.route.push("fly:" + toId); - // 传送 - core.ui.closePanel(); - core.setFlag('__isFlying__', true); - core.changeFloor(toId, stair, loc, null, function () { - core.removeFlag("__isFlying__"); - if (callback) callback(); - }); - - return true; -}, - "beforeBattle": function (enemyId, x, y) { - // 战斗前触发的事件,可以加上一些战前特效(详见下面支援的例子) - // 此函数在“检测能否战斗和自动存档”【之后】执行。如果需要更早的战前事件,请在插件中覆重写 core.events.doSystemEvent 函数。 - // 返回true则将继续战斗,返回false将不再战斗。 - - // ------ 支援技能 ------ // - if (x != null && y != null) { - var index = x + "," + y, - cache = core.status.checkBlock.cache[index] || {}, - guards = cache.guards || []; - // 如果存在支援怪 - if (guards.length > 0) { - // 记录flag,当前要参与支援的怪物 - core.setFlag("__guards__" + x + "_" + y, guards); - var actions = [{ "type": "playSound", "name": "跳跃" }]; - // 增加支援的特效动画(图块跳跃) - guards.forEach(function (g) { - core.push(actions, { "type": "jump", "from": [g[0], g[1]], "to": [x, y], "time": 300, "keep": false, "async": true }); + // 清除游戏数据 + // 这一步会清空状态栏和全部画布内容,并删除所有动态创建的画布 + core.clearStatus(); + // 初始化status + core.status = core.clone(core.initStatus, function (name) { + return name != 'hero' && name != 'maps'; }); - core.push(actions, [ - { "type": "waitAsync" }, // 等待所有异步事件执行完毕 - { "type": "setBlock", "number": enemyId, "loc": [[x, y]]}, // 重新设置怪物自身 - { "type": "battle", "loc": [x, y] } // 重要!重新触发本次战斗 - ]); - core.insertAction(actions); - return false; - } - } + core.control._bindRoutePush(); + core.status.played = true; + // 初始化人物,图标,统计信息 + core.status.hero = core.clone(hero); + window.hero = core.status.hero; + window.flags = core.status.hero.flags; + core.events.setHeroIcon(core.status.hero.image, true); + core.control._initStatistics(core.animateFrame.totalTime); + core.status.hero.statistics.totalTime = core.animateFrame.totalTime = + Math.max(core.status.hero.statistics.totalTime, core.animateFrame.totalTime); + core.status.hero.statistics.start = null; + // 初始难度 + core.status.hard = hard || ""; + // 初始化地图 + core.status.floorId = floorId; + core.status.maps = maps; + core.maps._resetFloorImages(); + // 初始化怪物和道具 + core.material.enemys = core.enemys.getEnemys(); + core.material.items = core.items.getItems(); + // 初始化全局数值和全局开关 + core.values = core.clone(core.data.values); + for (var key in values || {}) + core.values[key] = values[key]; + core.flags = core.clone(core.data.flags); + var globalFlags = core.getFlag("globalFlags", {}); + for (var key in globalFlags) + core.flags[key] = globalFlags[key]; + core._init_sys_flags(); + // 初始化界面,状态栏等 + core.resize(); + // 状态栏是否显示 + if (core.hasFlag('hideStatusBar')) + core.hideStatusBar(core.hasFlag('showToolbox')); + else + core.showStatusBar(); + // 隐藏右下角的音乐按钮 + core.dom.musicBtn.style.display = 'none'; + core.dom.enlargeBtn.style.display = 'none'; + }, + "win": function (reason, norank, noexit) { + // 游戏获胜事件 + // 请注意,成绩统计时是按照hp进行上传并排名 + // 可以先在这里对最终分数进行计算,比如将2倍攻击和5倍黄钥匙数量加到分数上 + // core.status.hero.hp += 2 * core.getRealStatus('atk') + 5 * core.itemCount('yellowKey'); - return true; -}, - "afterBattle": function (enemyId, x, y) { - // 战斗结束后触发的事件 + // 如果不退出,则临时存储数据 + if (noexit) { + core.status.extraEvent = core.clone(core.status.event); + } - var enemy = core.material.enemys[enemyId]; - var special = enemy.special; - - // 播放战斗音效和动画 - // 默认播放的动画;你也可以使用 - var animate = 'hand'; // 默认动画 - // 检查当前装备是否存在攻击动画 - var equipId = core.getEquip(0); - if (equipId && (core.material.items[equipId].equip || {}).animate) - animate = core.material.items[equipId].equip.animate; - // 你也可以在这里根据自己的需要,比如enemyId或special或flag来修改播放的动画效果 - // if (enemyId == '...') animate = '...'; - - // 检查该动画是否存在SE,如果不存在则使用默认音效 - if (!(core.material.animates[animate] || {}).se) - core.playSound('attack.mp3'); - - // 播放动画;如果不存在坐标(强制战斗)则播放到勇士自身 - if (x != null && y != null) - core.drawAnimate(animate, x, y); - else - core.drawHeroAnimate(animate); - - // 获得战斗伤害信息 - var damageInfo = core.getDamageInfo(enemyId, null, x, y) || {}; - // 战斗伤害 - var damage = damageInfo.damage; - // 当前战斗回合数,可用于战后所需的判定 - var turn = damageInfo.turn; - // 判定是否致死 - if (damage == null || damage >= core.status.hero.hp) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose('战斗失败'); - return; - } - - // 扣减体力值并记录统计数据 - core.status.hero.hp -= damage; - core.status.hero.statistics.battleDamage += damage; - core.status.hero.statistics.battle++; - - // 计算当前怪物的支援怪物 - var guards = []; - if (x != null && y != null) { - guards = core.getFlag("__guards__" + x + "_" + y, []); - core.removeFlag("__guards__" + x + "_" + y); - } - - // 获得金币 - var money = guards.reduce(function (curr, g) { - return curr + core.material.enemys[g[2]].money; - }, core.getEnemyValue(enemy, "money", x, y)); - if (core.hasItem('coin')) money *= 2; // 幸运金币:双倍 - if (core.hasFlag('curse')) money = 0; // 诅咒效果 - core.status.hero.money += money; - core.status.hero.statistics.money += money; - - // 获得经验 - var exp = guards.reduce(function (curr, g) { - return curr + core.material.enemys[g[2]].exp; - }, core.getEnemyValue(enemy, "exp", x, y)); - if (core.hasFlag('curse')) exp = 0; - core.status.hero.exp += exp; - core.status.hero.statistics.exp += exp; - - var hint = "打败 " + core.getEnemyValue(enemy, "name", x, y); - if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) - hint += ',' + core.getStatusLabel('money') + '+' + money; // hint += ",金币+" + money; - if (core.flags.statusBarItems.indexOf('enableExp') >= 0) - hint += ',' + core.getStatusLabel('exp') + '+' + exp; // hint += ",经验+" + exp; - core.drawTip(hint, enemy.id); - - // 中毒 - if (core.enemys.hasSpecial(special, 12)) { - core.triggerDebuff('get', 'poison'); - } - // 衰弱 - if (core.enemys.hasSpecial(special, 13)) { - core.triggerDebuff('get', 'weak'); - } - // 诅咒 - if (core.enemys.hasSpecial(special, 14)) { - core.triggerDebuff('get', 'curse'); - } - // 仇恨怪物将仇恨值减半 - if (core.enemys.hasSpecial(special, 17)) { - core.setFlag('hatred', Math.floor(core.getFlag('hatred', 0) / 2)); - } - // 自爆 - if (core.enemys.hasSpecial(special, 19)) { - core.status.hero.statistics.battleDamage += core.status.hero.hp - 1; - core.status.hero.hp = 1; - } - // 退化 - if (core.enemys.hasSpecial(special, 21)) { - core.status.hero.atk -= (enemy.atkValue || 0); - core.status.hero.def -= (enemy.defValue || 0); - if (core.status.hero.atk < 0) core.status.hero.atk = 0; - if (core.status.hero.def < 0) core.status.hero.def = 0; - } - // 增加仇恨值 - core.setFlag('hatred', core.getFlag('hatred', 0) + core.values.hatred); - - // 战后的技能处理,比如扣除魔力值 - if (core.flags.statusBarItems.indexOf('enableSkill') >= 0) { - // 检测当前开启的技能类型 - var skill = core.getFlag('skill', 0); - if (skill == 1) { // 技能1:二倍斩 - core.status.hero.mana -= 5; // 扣除5点魔力值 - } - // 关闭技能 - core.setFlag('skill', 0); - core.setFlag('skillName', '无'); - } - - - // 事件的处理 - var todo = []; - - // 加点事件 - var point = guards.reduce(function (curr, g) { - return curr + core.material.enemys[g[2]].point; - }, core.getEnemyValue(enemy, "point", x, y)) || 0; - if (core.flags.enableAddPoint && point > 0) { - core.push(todo, [{ "type": "insert", "name": "加点事件", "args": [point] }]); - } - - // 战后事件 - if (core.status.floorId != null) { - core.push(todo, core.floors[core.status.floorId].afterBattle[x + "," + y]); - } - core.push(todo, enemy.afterBattle); - - // 在这里增加其他的自定义事件需求 - /* - if (enemyId=='xxx') { - core.push(todo, [ - {"type": "...", ...}, - ]); - } - */ - - // 如果事件不为空,将其插入 - if (todo.length > 0) core.insertAction(todo, x, y); - - // 删除该点设置的怪物信息 - delete ((flags.enemyOnPoint||{})[core.status.floorId]||{})[x+","+y]; - - // 因为removeBlock和hideBlock都会刷新状态栏,因此将删除部分移动到这里并保证刷新只执行一次,以提升效率 - if (core.getBlock(x, y) != null) { - // 检查是否是重生怪物;如果是则仅隐藏不删除 - if (core.hasSpecial(enemy.special, 23)) { - core.hideBlock(x, y); - } else { - core.removeBlock(x, y); - } - } else { - core.updateStatusBar(); - } - - // 如果已有事件正在处理中 - if (core.status.event.id == null) - core.continueAutomaticRoute(); - else - core.clearContinueAutomaticRoute(); - -}, - "afterOpenDoor": function (doorId, x, y) { - // 开一个门后触发的事件 - - var todo = []; - // 检查该点的开门后事件 - if (core.status.floorId) { - core.push(todo, core.floors[core.status.floorId].afterOpenDoor[x + "," + y]); - } - // 检查批量开门事件 - var door = core.getBlockById(doorId); - if (door && door.event.doorInfo) { - core.push(todo, door.event.doorInfo.afterOpenDoor); - } - - if (todo.length > 0) core.insertAction(todo, x, y); - - if (core.status.event.id == null) - core.continueAutomaticRoute(); - else - core.clearContinueAutomaticRoute(); -}, - "afterGetItem": function (itemId, x, y, isGentleClick) { - // 获得一个道具后触发的事件 - // itemId:获得的道具ID;x和y是该道具所在的坐标 - // isGentleClick:是否是轻按触发的 - if (itemId.endsWith('Potion') && core.material.items[itemId].cls == 'items') - core.playSound('回血'); - else if (itemId.endsWith('Gem') && core.material.items[itemId].cls == 'items') - core.playSound('宝石') - else - core.playSound('获得道具'); - - var todo = []; - // 检查该点的获得道具后事件。 - if (core.status.floorId == null) return; - var event = core.floors[core.status.floorId].afterGetItem[x + "," + y]; - if (event && (event instanceof Array || !isGentleClick || !event.disableOnGentleClick)) { - core.unshift(todo, event); - } - - if (todo.length > 0) core.insertAction(todo, x, y); -}, - "afterPushBox": function () { - // 推箱子后的事件 - if (core.searchBlock('box').length == 0) { - // 可以通过if语句来进行开门操作 - /* - if (core.status.floorId=='xxx') { // 在某个楼层 - core.insertAction([ // 插入一条事件 - {"type": "openDoor", "loc": [x,y]} // 开门 - ]) - } - */ - } -} - }, - "enemys": { - "getSpecials": function () { - // 获得怪物的特殊属性,每一行定义一个特殊属性。 - // 分为五项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述 - // 第四项为该特殊属性的颜色,可以写十六进制 #RRGGBB 或者 [r,g,b,a] 四元数组 - // 第五项为该特殊属性的标记;目前 1 代表是地图类技能(需要进行遍历全图) - // 名字和描述可以直接写字符串,也可以写个function将怪物传进去 - return [ - [1, "先攻", "怪物首先攻击", "#ffcc33"], - [2, "魔攻", "怪物无视角色的防御", "#bbb0ff"], - [3, "坚固", "怪物防御不小于角色攻击-1", "#c0b088"], - [4, "2连击", "怪物每回合攻击2次", "#ffee77"], - [5, "3连击", "怪物每回合攻击3次", "#ffee77"], - [6, function (enemy) { return (enemy.n || '') + "连击"; }, function (enemy) { return "怪物每回合攻击" + (enemy.n || 4) + "次"; }, "#ffee77"], - [7, "破甲", function (enemy) { return "战斗前,怪物附加角色防御的" + Math.floor(100 * (enemy.defValue || core.values.breakArmor || 0)) + "%作为伤害"; }, "#88c0ff"], - [8, "反击", function (enemy) { return "战斗时,怪物每回合附加角色攻击的" + Math.floor(100 * (enemy.atkValue || core.values.counterAttack || 0)) + "%作为伤害,无视角色防御"; }, "#ffaa44"], - [9, "净化", function (enemy) { return "战斗前,怪物附加角色护盾的" + (enemy.n || core.values.purify) + "倍作为伤害"; }, "#80eed6"], - [10, "模仿", "怪物的攻防和角色攻防相等", "#b0c0dd"], - [11, "吸血", function (enemy) { return "战斗前,怪物首先吸取角色的" + Math.floor(100 * enemy.value || 0) + "%生命(约" + Math.floor((enemy.value || 0) * core.getStatus('hp')) + "点)作为伤害" + (enemy.add ? ",并把伤害数值加到自身生命上" : ""); }, "#dd4448"], - [12, "中毒", "战斗后,角色陷入中毒状态,每一步损失生命" + core.values.poisonDamage + "点", "#99ee88"], - [13, "衰弱", "战斗后,角色陷入衰弱状态,攻防暂时下降" + (core.values.weakValue >= 1 ? core.values.weakValue + "点" : parseInt(core.values.weakValue * 100) + "%"), "#f0bbcc"], - [14, "诅咒", "战斗后,角色陷入诅咒状态,战斗无法获得金币和经验", "#bbeef0"], - [15, "领域", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "范围内" + (enemy.range || 1) + "格时自动减生命" + (enemy.value || 0) + "点"; }, "#c677dd"], - [16, "夹击", "经过两只相同的怪物中间,角色生命值变成一半", "#bb99ee"], - [17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害;战斗后,释放一半的仇恨值。(每杀死一个怪物获得" + (core.values.hatred || 0) + "点仇恨值)", "#b0b666"], - [18, "阻击", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时自动减生命" + (enemy.value || 0) + "点,同时怪物后退一格"; }, "#8888e6"], - [19, "自爆", "战斗后角色的生命值变成1", "#ff6666"], - [20, "无敌", "角色无法打败怪物,除非拥有十字架", "#aaaaaa"], - [21, "退化", function (enemy) { return "战斗后角色永久下降" + (enemy.atkValue || 0) + "点攻击和" + (enemy.defValue || 0) + "点防御"; }], - [22, "固伤", function (enemy) { return "战斗前,怪物对角色造成" + (enemy.damage || 0) + "点固定伤害,未开启负伤时无视角色护盾。"; }, "#ff9977"], - [23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现", "#a0e0ff"], - [24, "激光", function (enemy) { return "经过怪物同行或同列时自动减生命" + (enemy.value || 0) + "点"; }, "#dda0dd"], - [25, "光环", function (enemy) { return (enemy.range != null ? ((enemy.zoneSquare ? "该怪物九宫格" : "该怪物十字") + enemy.range + "格范围内") : "同楼层所有") + "怪物生命提升" + (enemy.value || 0) + "%,攻击提升" + (enemy.atkValue || 0) + "%,防御提升" + (enemy.defValue || 0) + "%," + (enemy.add ? "可叠加" : "不可叠加"); }, "#e6e099", 1], - [26, "支援", "当周围一圈的怪物受到攻击时将上前支援,并组成小队战斗。", "#77c0b6", 1], - [27, "捕捉", function (enemy) { return "当走到怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时会强制进行战斗。"; }, "#c0ddbb"] - ]; -}, - "getEnemyInfo": function (enemy, hero, x, y, floorId) { - // 获得某个怪物变化后的数据;该函数将被伤害计算和怪物手册使用 - // 例如:坚固、模仿、仿攻等等 - // - // 参数说明: - // enemy:该怪物信息 - // hero_hp,hero_atk,hero_def,hero_mdef:勇士的生命攻防护盾数据 - // x,y:该怪物的坐标(查看手册和强制战斗时为undefined) - // floorId:该怪物所在的楼层 - // 后面三个参数主要是可以在光环等效果上可以适用(也可以按需制作部分范围光环效果) - floorId = floorId || core.status.floorId; - var hero_hp = core.getRealStatusOrDefault(hero, 'hp'), - hero_atk = core.getRealStatusOrDefault(hero, 'atk'), - hero_def = core.getRealStatusOrDefault(hero, 'def'), - hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'); - - var mon_hp = core.getEnemyValue(enemy, 'hp', x, y, floorId), - mon_atk = core.getEnemyValue(enemy, 'atk', x, y, floorId), - mon_def = core.getEnemyValue(enemy, 'def', x, y, floorId), - mon_special = core.getEnemyValue(enemy, 'special', x, y, floorId); - var mon_money = core.getEnemyValue(enemy, 'money', x, y, floorId), - mon_exp = core.getEnemyValue(enemy, 'exp', x, y, floorId), - mon_point = core.getEnemyValue(enemy, 'point', x, y, floorId); - // 模仿 - if (core.hasSpecial(mon_special, 10)) { - mon_atk = hero_atk; - mon_def = hero_def; - } - // 坚固 - if (core.hasSpecial(mon_special, 3) && mon_def < hero_atk - 1) { - mon_def = hero_atk - 1; - } - - var guards = []; - - // 光环和支援检查 - if (!core.status.checkBlock) core.status.checkBlock = {}; - - if (core.status.checkBlock.needCache) { - // 从V2.5.4开始,对光环效果增加缓存,以解决多次重复计算的问题,从而大幅提升运行效率。 - var hp_buff = 0, - atk_buff = 0, - def_buff = 0; - // 已经计算过的光环怪ID列表,用于判定叠加 - var usedEnemyIds = {}; - // 检查光环和支援的缓存 - var index = x != null && y != null ? (x + "," + y) : "floor"; - if (!core.status.checkBlock.cache) core.status.checkBlock.cache = {}; - var cache = core.status.checkBlock.cache[index]; - if (!cache) { - // 没有该点的缓存,则遍历每个图块 - core.extractBlocks(floorId); - core.status.maps[floorId].blocks.forEach(function (block) { - if (!block.disable) { - // 获得该图块的ID - var id = block.event.id, - enemy = core.material.enemys[id]; - // 检查【光环】技能,数字25 - if (enemy && core.hasSpecial(enemy.special, 25)) { - // 检查是否是范围光环 - var inRange = enemy.range == null; - if (enemy.range != null && x != null && y != null) { - var dx = Math.abs(block.x - x), - dy = Math.abs(block.y - y); - // 检查十字和九宫格光环 - if (dx + dy <= enemy.range) inRange = true; - if (enemy.zoneSquare && dx <= enemy.range && dy <= enemy.range) inRange = true; - } - // 检查是否可叠加 - if (inRange && (enemy.add || !usedEnemyIds[enemy.id])) { - hp_buff += enemy.value || 0; - atk_buff += enemy.atkValue || 0; - def_buff += enemy.defValue || 0; - usedEnemyIds[enemy.id] = true; - } - } - // 检查【支援】技能,数字26 - if (enemy && core.hasSpecial(enemy.special, 26) && - // 检查支援条件,坐标存在,距离为1,且不能是自己 - // 其他类型的支援怪,比如十字之类的话.... 看着做是一样的 - x != null && y != null && Math.abs(block.x - x) <= 1 && Math.abs(block.y - y) <= 1 && !(x == block.x && y == block.y)) { - // 记录怪物的x,y,ID - guards.push([block.x, block.y, id]); - } - - // TODO:如果有其他类型光环怪物在这里仿照添加检查 - // 注:新增新的类光环属性(需要遍历全图的)需要在特殊属性定义那里的第五项写1,参见光环和支援的特殊属性定义。 + // 游戏获胜事件 + core.ui.closePanel(); + var replaying = core.isReplaying(); + if (replaying) core.stopReplay(); + core.waitHeroToStop(function () { + if (!noexit) { + core.clearMap('all'); // 清空全地图 + core.deleteAllCanvas(); // 删除所有创建的画布 + core.dom.gif2.innerHTML = ""; } + reason = core.replaceText(reason); + core.drawText([ + "\t[" + (reason || "恭喜通关") + "]你的分数是${status:hp}。" + ], function () { + core.events.gameOver(reason || '', replaying, norank); + }) + }); + }, + "lose": function (reason) { + // 游戏失败事件 + core.ui.closePanel(); + var replaying = core.isReplaying(); + core.stopReplay(); + core.waitHeroToStop(function () { + core.drawText([ + "\t[" + (reason || "结局1") + "]你死了。\n如题。" + ], function () { + core.events.gameOver(null, replaying); + }); + }) + }, + "changingFloor": function (floorId, heroLoc) { + // 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻 + // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置 + + // ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- // + var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null + var fromLoad = core.hasFlag('__fromLoad__'); // 是否是读档造成的切换 + var isFlying = core.hasFlag('__isFlying__'); // 是否是楼传造成的切换 + if (!fromLoad && !(isFlying && currentId == floorId)) { + if (!core.hasFlag("__leaveLoc__")) core.setFlag("__leaveLoc__", {}); + if (currentId != null) core.getFlag("__leaveLoc__")[currentId] = core.clone(core.status.hero.loc); + } + + // 可以对currentId进行判定,比如删除某些自定义图层等 + // if (currentId == 'MT0') { + // core.deleteAllCanvas(); + // } + + // 根据分区信息自动砍层与恢复 + if (core.autoRemoveMaps) core.autoRemoveMaps(floorId); + + // 重置画布尺寸 + core.maps.resizeMap(floorId); + // 设置勇士的位置 + heroLoc.direction = core.turnDirection(heroLoc.direction); + core.status.hero.loc = heroLoc; + // 检查重生怪并重置 + if (!fromLoad) { + core.extractBlocks(floorId); + core.status.maps[floorId].blocks.forEach(function (block) { + if (block.disable && core.enemys.hasSpecial(block.event.id, 23)) { + block.disable = false; + core.setMapBlockDisabled(floorId, block.x, block.y, false); + core.maps._updateMapArray(floorId, block.x, block.y); + } + }); + core.control.gatherFollowers(); + } + + // ---------- 重绘新地图;这一步将会设置core.status.floorId ---------- // + core.drawMap(floorId); + + // 切换楼层BGM + if (core.status.maps[floorId].bgm) { + var bgm = core.status.maps[floorId].bgm; + if (bgm instanceof Array) bgm = bgm[Math.floor(Math.random() * bgm.length)]; // 多个bgm则随机播放一个 + if (!core.hasFlag("__bgm__")) core.playBgm(bgm); + } else if (fromLoad && !core.hasFlag("__bgm__")) { + core.pauseBgm(); + } + // 更改画面色调 + var color = core.getFlag('__color__', null); + if (!color && core.status.maps[floorId].color) + color = core.status.maps[floorId].color; + core.clearMap('curtain'); + core.status.curtainColor = color; + if (color) core.fillRect('curtain', 0, 0, core.__PIXELS__, core.__PIXELS__, core.arrayToRGBA(color)); + // 更改天气 + var weather = core.getFlag('__weather__', null); + if (!weather && core.status.maps[floorId].weather) + weather = core.status.maps[floorId].weather; + if (weather) + core.setWeather(weather[0], weather[1]); + else core.setWeather(); + + // ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等 + + }, + "afterChangeFloor": function (floorId) { + // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 + // floorId是切换到的楼层 + + // 如果是读档,则进行检查(是否需要恢复事件) + if (core.hasFlag('__fromLoad__')) { + core.events.recoverEvents(core.getFlag("__events__")); + core.removeFlag("__events__"); + } else { + // 每次抵达楼层执行的事件 + core.insertAction(core.floors[floorId].eachArrive); + + // 首次抵达楼层时执行的事件(后插入,先执行) + if (!core.hasVisitedFloor(floorId)) { + core.insertAction(core.floors[floorId].firstArrive); + core.visitFloor(floorId); + } + } + }, + "flyTo": function (toId, callback) { + // 楼层传送器的使用,从当前楼层飞往toId + // 如果不能飞行请返回false + + var fromId = core.status.floorId; + + // 检查能否飞行 + if (!core.status.maps[fromId].canFlyFrom || !core.status.maps[toId].canFlyTo || !core.hasVisitedFloor(toId)) { + core.playSound('操作失败'); + core.drawTip("无法飞往" + core.status.maps[toId].title + "!", 'fly'); + return false; + } + + // 平面塔模式 + var stair = null, + loc = null; + if (core.flags.flyRecordPosition) { + loc = core.getFlag("__leaveLoc__", {})[toId] || null; + } + if (core.status.maps[toId].flyPoint != null && core.status.maps[toId].flyPoint.length == 2) { + stair = 'flyPoint'; + } + if (stair == null && loc == null) { + // 获得两个楼层的索引,以决定是上楼梯还是下楼梯 + var fromIndex = core.floorIds.indexOf(fromId), + toIndex = core.floorIds.indexOf(toId); + var stair = fromIndex <= toIndex ? "downFloor" : "upFloor"; + // 地下层:同层传送至上楼梯 + if (fromIndex == toIndex && core.status.maps[fromId].underGround) stair = "upFloor"; + } + + // 记录录像 + core.status.route.push("fly:" + toId); + // 传送 + core.ui.closePanel(); + core.setFlag('__isFlying__', true); + core.changeFloor(toId, stair, loc, null, function () { + core.removeFlag("__isFlying__"); + if (callback) callback(); }); - core.status.checkBlock.cache[index] = { "hp_buff": hp_buff, "atk_buff": atk_buff, "def_buff": def_buff, "guards": guards }; - } else { - // 直接使用缓存数据 - hp_buff = cache.hp_buff; - atk_buff = cache.atk_buff; - def_buff = cache.def_buff; - guards = cache.guards; - } + return true; + }, + "beforeBattle": function (enemyId, x, y) { + // 战斗前触发的事件,可以加上一些战前特效(详见下面支援的例子) + // 此函数在“检测能否战斗和自动存档”【之后】执行。如果需要更早的战前事件,请在插件中覆重写 core.events.doSystemEvent 函数。 + // 返回true则将继续战斗,返回false将不再战斗。 - // 增加比例;如果要增加数值可以直接在这里修改 - mon_hp *= (1 + hp_buff / 100); - mon_atk *= (1 + atk_buff / 100); - mon_def *= (1 + def_buff / 100); - } - - // TODO:可以在这里新增其他的怪物数据变化 - // 比如仿攻(怪物攻击不低于勇士攻击): - // if (core.hasSpecial(mon_special, 27) && mon_atk < hero_atk) { - // mon_atk = hero_atk; - // } - // 也可以按需增加各种自定义内容 - - return { - "hp": Math.floor(mon_hp), - "atk": Math.floor(mon_atk), - "def": Math.floor(mon_def), - "money": Math.floor(mon_money), - "exp": Math.floor(mon_exp), - "point": Math.floor(mon_point), - "special": mon_special, - "guards": guards, // 返回支援情况 - }; -}, - "getDamageInfo": function (enemy, hero, x, y, floorId) { - // 获得战斗伤害信息(实际伤害计算函数) - // - // 参数说明: - // enemy:该怪物信息 - // hero:勇士的当前数据;如果对应项不存在则会从core.status.hero中取。 - // x,y:该怪物的坐标(查看手册和强制战斗时为undefined) - // floorId:该怪物所在的楼层 - // 后面三个参数主要是可以在光环等效果上可以适用 - floorId = floorId || core.status.floorId; - - var hero_hp = core.getRealStatusOrDefault(hero, 'hp'), - hero_atk = core.getRealStatusOrDefault(hero, 'atk'), - hero_def = core.getRealStatusOrDefault(hero, 'def'), - hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'), - origin_hero_hp = core.getStatusOrDefault(hero, 'hp'), - origin_hero_atk = core.getStatusOrDefault(hero, 'atk'), - origin_hero_def = core.getStatusOrDefault(hero, 'def'); - - // 勇士的负属性都按0计算 - hero_hp = Math.max(0, hero_hp); - hero_atk = Math.max(0, hero_atk); - hero_def = Math.max(0, hero_def); - hero_mdef = Math.max(0, hero_mdef); - - // 怪物的各项数据 - // 对坚固模仿等处理扔到了脚本编辑-getEnemyInfo之中 - var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y, floorId); - var mon_hp = enemyInfo.hp, - mon_atk = enemyInfo.atk, - mon_def = enemyInfo.def, - mon_special = enemyInfo.special; - - // 技能的处理 - if (core.getFlag('skill', 0) == 1) { // 开启了技能1:二倍斩 - hero_atk *= 2; // 计算时攻击力翻倍 - } - - // 如果是无敌属性,且勇士未持有十字架 - if (core.hasSpecial(mon_special, 20) && !core.hasItem("cross")) - return null; // 不可战斗 - - // 战前造成的额外伤害(可被护盾抵消) - var init_damage = 0; - - // 吸血 - if (core.hasSpecial(mon_special, 11)) { - var vampire_damage = hero_hp * enemy.value; - - // 如果有神圣盾免疫吸血等可以在这里写 - // 也可以用hasItem和hasEquip来判定装备 - // if (core.hasFlag('shield5')) vampire_damage = 0; - - vampire_damage = Math.floor(vampire_damage) || 0; - // 加到自身 - if (enemy.add) // 如果加到自身 - mon_hp += vampire_damage; - - init_damage += vampire_damage; - } - - // 每回合怪物对勇士造成的战斗伤害 - var per_damage = mon_atk - hero_def; - // 魔攻:战斗伤害就是怪物攻击力 - if (core.hasSpecial(mon_special, 2)) per_damage = mon_atk; - // 战斗伤害不能为负值 - if (per_damage < 0) per_damage = 0; - - // 2连击 & 3连击 & N连击 - if (core.hasSpecial(mon_special, 4)) per_damage *= 2; - if (core.hasSpecial(mon_special, 5)) per_damage *= 3; - if (core.hasSpecial(mon_special, 6)) per_damage *= (enemy.n || 4); - - // 每回合的反击伤害;反击是按照勇士的攻击次数来计算回合 - var counterDamage = 0; - if (core.hasSpecial(mon_special, 8)) - counterDamage += Math.floor((enemy.atkValue || core.values.counterAttack) * hero_atk); - - // 先攻 - if (core.hasSpecial(mon_special, 1)) init_damage += per_damage; - - // 破甲 - if (core.hasSpecial(mon_special, 7)) - init_damage += Math.floor((enemy.defValue || core.values.breakArmor) * hero_def); - - // 净化 - if (core.hasSpecial(mon_special, 9)) - init_damage += Math.floor((enemy.n || core.values.purify) * hero_mdef); - - // 勇士每回合对怪物造成的伤害 - var hero_per_damage = Math.max(hero_atk - mon_def, 0); - - // 如果没有破防,则不可战斗 - if (hero_per_damage <= 0) return null; - - // 勇士的攻击回合数;为怪物生命除以每回合伤害向上取整 - var turn = Math.ceil(mon_hp / hero_per_damage); - - // ------ 支援 ----- // - // 这个递归最好想明白为什么,flag:__extraTurn__是怎么用的 - var guards = core.getFlag("__guards__" + x + "_" + y, enemyInfo.guards); - var guard_before_current_enemy = false; // ------ 支援怪是先打(true)还是后打(false)? - turn += core.getFlag("__extraTurn__", 0); - if (guards.length > 0) { - if (!guard_before_current_enemy) { // --- 先打当前怪物,记录当前回合数 - core.setFlag("__extraTurn__", turn); - } - // 获得那些怪物组成小队战斗 - for (var i = 0; i < guards.length; i++) { - var gx = guards[i][0], - gy = guards[i][1], - gid = guards[i][2]; - // 递归计算支援怪伤害信息,这里不传x,y保证不会重复调用 - // 这里的mdef传0,因为护盾应该只会被计算一次 - var info = core.enemys.getDamageInfo(core.material.enemys[gid], { hp: origin_hero_hp, atk: origin_hero_atk, def: origin_hero_def, mdef: 0 }); - if (info == null) { // 小队中任何一个怪物不可战斗,直接返回null - core.removeFlag("__extraTurn__"); - return null; - } - // 已经进行的回合数 - core.setFlag("__extraTurn__", info.turn); - init_damage += info.damage; - } - if (guard_before_current_enemy) { // --- 先打支援怪物,增加当前回合数 - turn += core.getFlag("__extraTurn__", 0); - } - } - core.removeFlag("__extraTurn__"); - // ------ 支援END ------ // - - // 最终伤害:初始伤害 + 怪物对勇士造成的伤害 + 反击伤害 - var damage = init_damage + (turn - 1) * per_damage + turn * counterDamage; - // 再扣去护盾 - damage -= hero_mdef; - - // 检查是否允许负伤 - if (!core.flags.enableNegativeDamage) - damage = Math.max(0, damage); - - // 最后处理仇恨和固伤(因为这两个不能被护盾减伤) - if (core.hasSpecial(mon_special, 17)) { // 仇恨 - damage += core.getFlag('hatred', 0); - } - if (core.hasSpecial(mon_special, 22)) { // 固伤 - damage += enemy.damage || 0; - } - - return { - "mon_hp": Math.floor(mon_hp), - "mon_atk": Math.floor(mon_atk), - "mon_def": Math.floor(mon_def), - "init_damage": Math.floor(init_damage), - "per_damage": Math.floor(per_damage), - "hero_per_damage": Math.floor(hero_per_damage), - "turn": Math.floor(turn), - "damage": Math.floor(damage) - }; -} - }, - "actions": { - "onKeyUp": function (keyCode, altKey) { - // 键盘按键处理,可以在这里自定义快捷键列表 - // keyCode:当前按键的keyCode(每个键的keyCode自行百度) - // altKey:Alt键是否被按下,为true代表同时按下了Alt键 - // 可以在这里任意增加或编辑每个按键的行为 - - // 如果处于正在行走状态,则不处理 - if (core.isMoving()) - return; - - // Alt+0~9,快捷换上套装 - if (altKey && keyCode >= 48 && keyCode <= 57) { - core.items.quickLoadEquip(keyCode - 48); - return; - } - - // 根据keyCode值来执行对应操作 - switch (keyCode) { - case 27: // ESC:打开菜单栏 - core.openSettings(true); - break; - case 88: // X:使用怪物手册 - core.openBook(true); - break; - case 71: // G:使用楼传器 - core.useFly(true); - break; - case 65: // A:读取自动存档(回退) - core.doSL("autoSave", "load"); - break; - case 87: // W:撤销回退 - core.doSL("autoSave", "reload"); - break; - case 83: // S:存档 - core.save(true); - break; - case 68: // D:读档 - core.load(true); - break; - case 69: // E:打开光标 - core.ui._drawCursor(); - break; - case 84: // T:打开道具栏 - core.openToolbox(true); - break; - case 81: // Q:打开装备栏 - core.openEquipbox(true); - break; - case 90: // Z:转向 - core.turnHero(); - break; - case 86: // V:打开快捷商店列表 - core.openQuickShop(true); - break; - case 32: // SPACE:轻按 - core.getNextItem(); - break; - case 82: // R:回放录像 - core.ui._drawReplay(); - break; - case 33: - case 34: // PgUp/PgDn:浏览地图 - core.ui._drawViewMaps(); - break; - case 66: // B:打开数据统计 - core.ui._drawStatistics(); - break; - case 72: // H:打开帮助页面 - core.ui._drawHelp(); - break; - case 77: // M:打开存档笔记 - core.actions._clickNotes_show(); - break; - case 78: // N:重新开始 - core.confirmRestart(); - break; - case 79: // O:查看工程 - core.actions._clickGameInfo_openProject(); - break; - case 80: // P:游戏主页 - core.actions._clickGameInfo_openComments(); - break; - case 49: // 快捷键1: 破 - if (core.hasItem('pickaxe')) { - core.status.route.push("key:49"); // 将按键记在录像中 - core.useItem('pickaxe', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 - } - break; - case 50: // 快捷键2: 炸 - if (core.hasItem('bomb')) { - core.status.route.push("key:50"); // 将按键记在录像中 - core.useItem('bomb', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 - } - break; - case 51: // 快捷键3: 飞 - if (core.hasItem('centerFly')) { - core.ui._drawCenterFly(); - } - break; - case 52: // 快捷键4:破冰/冰冻/地震/上下楼器/... 其他道具依次判断 - { - var list = ["icePickaxe", "freezeBadge", "earthquake", "upFly", "downFly", "jumpShoes", "lifeWand", "poisonWine", "weakWine", "curseWine", "superWine"]; - for (var i = 0; i < list.length; i++) { - var itemId = list[i]; - if (core.canUseItem(itemId)) { - core.status.route.push("key:52"); - core.useItem(itemId, true); - break; + // ------ 支援技能 ------ // + if (x != null && y != null) { + var index = x + "," + y, + cache = core.status.checkBlock.cache[index] || {}, + guards = cache.guards || []; + // 如果存在支援怪 + if (guards.length > 0) { + // 记录flag,当前要参与支援的怪物 + core.setFlag("__guards__" + x + "_" + y, guards); + var actions = [{ "type": "playSound", "name": "跳跃" }]; + // 增加支援的特效动画(图块跳跃) + guards.forEach(function (g) { + core.push(actions, { "type": "jump", "from": [g[0], g[1]], "to": [x, y], "time": 300, "keep": false, "async": true }); + }); + core.push(actions, [ + { "type": "waitAsync" }, // 等待所有异步事件执行完毕 + { "type": "setBlock", "number": enemyId, "loc": [[x, y]] }, // 重新设置怪物自身 + { "type": "battle", "loc": [x, y] } // 重要!重新触发本次战斗 + ]); + core.insertAction(actions); + return false; } } - } - break; - case 53: // 5:读取自动存档(回退),方便手机版操作 - core.doSL("autoSave", "load"); - break; - case 54: // 6:撤销回退,方便手机版操作 - core.doSL("autoSave", "reload"); - break; - case 55: // 快捷键7:绑定为轻按,方便手机版操作 - core.getNextItem(); - break; - case 118: // F7:开启debug模式 - core.debug(); - break; - case 70: // F:开启技能“二倍斩” - // 检测是否拥有“二倍斩”这个技能道具 - if (core.hasItem('skill1')) { - core.status.route.push("key:70"); - core.useItem('skill1', true); - } - break; - // 在这里可以任意新增或编辑已有的快捷键内容 - /* - case 0: // 使用该按键的keyCode - // 还可以再判定altKey是否被按下,即 if (altKey) { ... - // ... 在这里写你要执行脚本 - // **强烈建议所有新增的自定义快捷键均能给个对应的道具可点击,以方便手机端的行为** - if (core.hasItem('...')) { - core.status.route.push("key:0"); - core.useItem('...', true); // 增加true代表该使用道具不计入录像 + return true; + }, + "afterBattle": function (enemyId, x, y) { + // 战斗结束后触发的事件 + + var enemy = core.material.enemys[enemyId]; + var special = enemy.special; + + // 播放战斗音效和动画 + // 默认播放的动画;你也可以使用 + var animate = 'hand'; // 默认动画 + // 检查当前装备是否存在攻击动画 + var equipId = core.getEquip(0); + if (equipId && (core.material.items[equipId].equip || {}).animate) + animate = core.material.items[equipId].equip.animate; + // 你也可以在这里根据自己的需要,比如enemyId或special或flag来修改播放的动画效果 + // if (enemyId == '...') animate = '...'; + + // 检查该动画是否存在SE,如果不存在则使用默认音效 + if (!(core.material.animates[animate] || {}).se) + core.playSound('attack.mp3'); + + // 播放动画;如果不存在坐标(强制战斗)则播放到勇士自身 + if (x != null && y != null) + core.drawAnimate(animate, x, y); + else + core.drawHeroAnimate(animate); + + // 获得战斗伤害信息 + var damageInfo = core.getDamageInfo(enemyId, null, x, y) || {}; + // 战斗伤害 + var damage = damageInfo.damage; + // 当前战斗回合数,可用于战后所需的判定 + var turn = damageInfo.turn; + // 判定是否致死 + if (damage == null || damage >= core.status.hero.hp) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose('战斗失败'); + return; } - break; - */ - } - -}, - "onStatusBarClick": function (px, py, vertical) { - // 点击状态栏时触发的事件,仅在自绘状态栏开启时生效 - // px和py为点击的像素坐标 - // vertical为录像播放过程中的横竖屏信息 - // - // 横屏模式下状态栏的画布大小是 129*416 (开启拓展装备栏后是 129*457) - // 竖屏模式下状态栏的画布大小是 416*(32*rows+9) 其中rows为状态栏行数,即全塔属性中statusCanvasRowsOnMobile值 - // 可以使用 _isVertical() 来判定当前是否是竖屏模式 - - // 判定当前是否是竖屏模式。录像播放过程中可能会记录当时的横竖屏信息以覆盖。 - var _isVertical = function () { - if (core.isReplaying() && vertical != null) return vertical; - return core.domStyle.isVertical; - } - - // 如果正在执行事件,则忽略 - if (core.status.lockControl) return; - // 如果当前正在行走,则忽略;也可以使用 core.waitHeroToStop(callback) 来停止行走再回调执行脚本 - if (core.isMoving()) return; - - // 判定px和py来执行自己的脚本内容.... 注意横竖屏 - // console.log("onStatusBarClick: ", px, py, _isVertical()); - - // 样例一:点击某个区域后使用一个道具 - /* - if (core.hasItem("pickaxe")) { - if (_isVertical()) { - // 竖屏模式下 - if (px >= 200 && px <= 250 && py >= 50 && py <= 100) { - core.useItem("pickaxe"); - } - } else { - // 横屏模式下 - if (px >= 50 && px <= 100 && py >= 200 && py <= 250) { - core.useItem("pickaxe"); - } - } - } - */ - - // 样例二:点击某个区域后执行一段公共事件或脚本 - /* - if (core.hasFlag("xxx")) { - if (_isVertical()) { - // 竖屏模式下 - if (px >= 200 && px <= 250 && py >= 50 && py <= 100) { - // 记录点击坐标。这里的1代表此时是竖屏! - core.status.route.push("click:1:" + px + ":" + py); - - // 可以插入公共事件 / 普通事件 / 执行一段脚本(如打开自绘UI或增减flag) - core.insertCommonEvent("道具商店"); - // core.insertAction(["一段事件"]); - // core.openItemShop("shop1"); - } - } else { - // 横屏模式下 - if (px >= 50 && px <= 100 && py >= 200 && py <= 250) { - // 记录点击坐标。这里的0代表此时是横屏! - core.status.route.push("click:0:" + px + ":" + py); - - // 可以插入公共事件 / 普通事件 / 执行一段脚本(如打开自绘UI或增减flag) - core.insertCommonEvent("道具商店"); - // core.insertAction(["一段事件"]); - // core.openItemShop("shop1"); - } - } - } - */ - -} - }, - "control": { - "saveData": function () { - // 存档操作,此函数应该返回“具体要存档的内容” - - // 差异化存储values - var values = {}; - for (var key in core.values) { - if (!core.same(core.values[key], core.data.values[key])) - values[key] = core.clone(core.values[key]); - } - - // 要存档的内容 - var data = { - 'floorId': core.status.floorId, - 'hero': core.clone(core.status.hero), - 'hard': core.status.hard, - 'maps': core.maps.saveMap(), - 'route': core.encodeRoute(core.status.route), - 'values': values, - 'version': core.firstData.version, - 'guid': core.getGuid(), - "time": new Date().getTime() - }; - - return data; -}, - "loadData": function (data, callback) { - // 读档操作;从存储中读取了内容后的行为 - - // 重置游戏和路线 - core.resetGame(data.hero, data.hard, data.floorId, core.maps.loadMap(data.maps, null, data.hero.flags), data.values); - core.status.route = core.decodeRoute(data.route); - core.control._bindRoutePush(); - // 文字属性,全局属性 - core.status.textAttribute = core.getFlag('textAttribute', core.status.textAttribute); - var toAttribute = core.getFlag('globalAttribute', core.status.globalAttribute); - if (!core.same(toAttribute, core.status.globalAttribute)) { - core.status.globalAttribute = toAttribute; - core.resize(); - } - // 重置音量 - core.events.setVolume(core.getFlag("__volume__", 1), 0); - // 加载勇士图标 - var icon = core.status.hero.image; - icon = core.getMappedName(icon); - if (core.material.images.images[icon]) { - core.material.images.hero = core.material.images.images[icon]; - core.material.icons.hero.width = core.material.images.images[icon].width / 4; - core.material.icons.hero.height = core.material.images.images[icon].height / 4; - } - core.setFlag('__fromLoad__', true); - - // TODO:增加自己的一些读档处理 - - // 切换到对应的楼层 - core.changeFloor(data.floorId, null, data.hero.loc, 0, function () { - // TODO:可以在这里设置读档后播放BGM - if (core.hasFlag("__bgm__")) { // 持续播放 - core.playBgm(core.getFlag("__bgm__")); - } - - core.removeFlag('__fromLoad__'); - if (callback) callback(); - }); -}, - "getStatusLabel": function (name) { - // 返回某个状态英文名的对应中文标签,如atk -> 攻击,def -> 防御等。 - // 请注意此项仅影响 libs/ 下的内容(如绘制怪物手册、数据统计等) - // 自行定义的(比如获得道具效果)中用到的“攻击+3”等需要自己去对应地方修改 - - return { - name: "名称", - lv: "等级", - hpmax: "生命上限", - hp: "生命", - manamax: "魔力上限", - mana: "魔力", - atk: "攻击", - def: "防御", - mdef: "护盾", - money: "金币", - exp: "经验", - point: "加点", - steps: "步数", - } [name] || name; -}, - "triggerDebuff": function (action, type) { - // 毒衰咒效果的获得与解除 - // action:获得还是解除;'get'表示获得,'remove'表示解除 - // type:一个数组表示获得了哪些毒衰咒效果;poison, weak,curse - if (!(type instanceof Array)) type = [type]; - - if (action == 'get') { - if (core.inArray(type, 'poison') && !core.hasFlag("poison")) { - // 获得毒效果 - core.setFlag('poison', true); - } - if (core.inArray(type, 'weak') && !core.hasFlag('weak')) { - // 获得衰效果 - core.setFlag('weak', true); - if (core.values.weakValue >= 1) { - // >=1,直接扣数值 - core.addStatus('atk', -core.values.weakValue); - core.addStatus('def', -core.values.weakValue); - } else { - // <1,扣比例 - core.addBuff('atk', -core.values.weakValue); - core.addBuff('def', -core.values.weakValue); - } - } - if (core.inArray(type, 'curse') && !core.hasFlag('curse')) { - // 获得咒效果 - core.setFlag('curse', true); - } - } else if (action == 'remove') { - var success = false; - if (core.inArray(type, "poison") && core.hasFlag("poison")) { - success = true; - // 移除毒效果 - core.setFlag("poison", false); - } - if (core.inArray(type, "weak") && core.hasFlag("weak")) { - success = true; - // 移除衰效果 - core.setFlag("weak", false); - if (core.values.weakValue >= 1) { - // >=1,直接扣数值 - core.addStatus('atk', core.values.weakValue); - core.addStatus('def', core.values.weakValue); - } else { - // <1,扣比例 - core.addBuff('atk', core.values.weakValue); - core.addBuff('def', core.values.weakValue); - } - } - if (core.inArray(type, "curse") && core.hasFlag("curse")) { - success = true; - // 移除咒效果 - core.setFlag("curse", false); - } - if (success) core.playSound('回血'); - } -}, - "updateStatusBar": function () { - // 更新状态栏 - - // 检查等级 - core.events.checkLvUp(); - - // 检查HP上限 - if (core.flags.statusBarItems.indexOf('enableHPMax') >= 0) { - core.setStatus('hp', Math.min(core.getRealStatus('hpmax'), core.getStatus('hp'))); - } - - // 设置楼层名 - if (core.status.floorId) { - core.setStatusBarInnerHTML('floor', core.status.maps[core.status.floorId].name); - } - - // 设置勇士名字和图标 - core.setStatusBarInnerHTML('name', core.getStatus('name')); - // 设置等级名称 - core.setStatusBarInnerHTML('lv', core.getLvName()); - - // 设置生命上限、生命值、攻防护盾金币和经验值 - var statusList = ['hpmax', 'hp', 'mana', 'atk', 'def', 'mdef', 'money', 'exp']; - statusList.forEach(function (item) { - // 向下取整 - core.status.hero[item] = Math.floor(core.status.hero[item]); - // 大数据格式化 - core.setStatusBarInnerHTML(item, core.getRealStatus(item)); - }); - - // 设置魔力值; status:manamax 只有在非负时才生效。 - if (core.status.hero.manamax != null && core.getRealStatus('manamax') >= 0) { - core.status.hero.mana = Math.min(core.status.hero.mana, core.getRealStatus('manamax')); - core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.getRealStatus('manamax')); - } else { - core.setStatusBarInnerHTML("mana", core.status.hero.mana); - } - // 设置技能栏 - // 可以用flag:skill表示当前开启的技能类型,flag:skillName显示技能名;详见文档-个性化-技能塔的支持 - core.setStatusBarInnerHTML('skill', core.getFlag('skillName', '无')); - - // 可以在这里添加自己额外的状态栏信息,比如想攻击显示 +0.5 可以这么写: - // if (core.hasFlag('halfAtk')) core.setStatusBarInnerHTML('atk', core.statusBar.atk.innerText + "+0.5"); - - // 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值 - - // 进阶 - if (core.flags.statusBarItems.indexOf('enableLevelUp') >= 0) { - core.setStatusBarInnerHTML('up', core.formatBigNumber(core.getNextLvUpNeed()) || ""); - } else core.setStatusBarInnerHTML('up', ""); - - // 钥匙 - var keys = ['yellowKey', 'blueKey', 'redKey', 'greenKey']; - keys.forEach(function (key) { - core.setStatusBarInnerHTML(key, core.setTwoDigits(core.itemCount(key))); - }); - // 毒衰咒 - core.setStatusBarInnerHTML('poison', core.hasFlag('poison') ? "毒" : ""); - core.setStatusBarInnerHTML('weak', core.hasFlag('weak') ? "衰" : ""); - core.setStatusBarInnerHTML('curse', core.hasFlag('curse') ? "咒" : ""); - // 破炸飞 - core.setStatusBarInnerHTML('pickaxe', "破" + core.itemCount('pickaxe')); - core.setStatusBarInnerHTML('bomb', "炸" + core.itemCount('bomb')); - core.setStatusBarInnerHTML('fly', "飞" + core.itemCount('centerFly')); - - // 难度 - if (core.statusBar.hard.innerText != core.status.hard) { - core.statusBar.hard.innerText = core.status.hard; - } - var hardColor = core.getFlag('__hardColor__', 'red'); - if (core.statusBar.hard.getAttribute('_style') != hardColor) { - core.statusBar.hard.style.color = hardColor; - core.statusBar.hard.setAttribute('_style', hardColor); - } - // 自定义状态栏绘制 - core.drawStatusBar(); - - // 更新阻激夹域的伤害值 - core.updateCheckBlock(); - // 更新全地图显伤 - core.updateDamage(); -}, - "updateCheckBlock": function (floorId) { - // 领域、夹击、阻击等的伤害值计算 - floorId = floorId || core.status.floorId; - if (!floorId || !core.status.maps) return; - - var width = core.floors[floorId].width, - height = core.floors[floorId].height; - var blocks = core.getMapBlocksObj(floorId); - - var damage = {}, // 每个点的伤害值 - type = {}, // 每个点的伤害类型 - repulse = {}, // 每个点的阻击怪信息 - ambush = {}; // 每个点的捕捉信息 - var betweenAttackLocs = {}; // 所有可能的夹击点 - var needCache = false; - var canGoDeadZone = core.flags.canGoDeadZone; - core.flags.canGoDeadZone = true; - - // 计算血网和领域、阻击、激光的伤害,计算捕捉信息 - for (var loc in blocks) { - var block = blocks[loc], - x = block.x, - y = block.y, - id = block.event.id, - enemy = core.material.enemys[id]; - if (block.disable) continue; - - type[loc] = type[loc] || {}; - - // 血网 - // 如需调用当前楼层的ratio可使用 core.status.maps[floorId].ratio - if (id == 'lavaNet' && !core.hasItem('amulet')) { - damage[loc] = (damage[loc] || 0) + core.values.lavaDamage; - type[loc][(block.event.name || "血网") + "伤害"] = true; - } - - // 领域 - // 如果要防止领域伤害,可以直接简单的将 flag:no_zone 设为true - if (enemy && core.hasSpecial(enemy.special, 15) && !core.hasFlag('no_zone')) { - // 领域范围,默认为1 - var range = enemy.range || 1; - // 是否是九宫格领域 - var zoneSquare = false; - if (enemy.zoneSquare != null) zoneSquare = enemy.zoneSquare; - // 在范围内进行搜索,增加领域伤害值 - for (var dx = -range; dx <= range; dx++) { - for (var dy = -range; dy <= range; dy++) { - if (dx == 0 && dy == 0) continue; - var nx = x + dx, - ny = y + dy, - currloc = nx + "," + ny; - if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; - // 如果是十字领域,则还需要满足 |dx|+|dy|<=range - if (!zoneSquare && Math.abs(dx) + Math.abs(dy) > range) continue; - damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = type[currloc] || {}; - type[currloc]["领域伤害"] = true; - } - } - } - - // 阻击 - // 如果要防止阻击伤害,可以直接简单的将 flag:no_repulse 设为true - if (enemy && core.hasSpecial(enemy.special, 18) && !core.hasFlag('no_repulse')) { - var scan = enemy.zoneSquare ? core.utils.scan2 : core.utils.scan; - for (var dir in scan) { - var nx = x + scan[dir].x, - ny = y + scan[dir].y, - currloc = nx + "," + ny; - if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; - damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = type[currloc] || {}; - type[currloc]["阻击伤害"] = true; - - var rdir = core.turnDirection(":back", dir); - // 检查下一个点是否存在事件(从而判定是否移动) - var rnx = x + scan[rdir].x, - rny = y + scan[rdir].y; - if (rnx < 0 || rnx >= width || rny < 0 || rny >= height) continue; - // 如需禁止阻击被推到已隐藏的事件处(如重生怪处),可将这一句的false改为true - if (core.getBlock(rnx, rny, floorId, false) != null) continue; - if (core.utils.scan[rdir] && !core.canMoveHero(x, y, rdir, floorId)) continue; - repulse[currloc] = (repulse[currloc] || []).concat([ - [x, y, id, rdir] - ]); - } - } - - // 激光 - // 如果要防止激光伤害,可以直接简单的将 flag:no_laser 设为true - if (enemy && core.hasSpecial(enemy.special, 24) && !core.hasFlag("no_laser")) { - for (var nx = 0; nx < width; nx++) { - var currloc = nx + "," + y; - if (nx != x) { - damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = type[currloc] || {}; - type[currloc]["激光伤害"] = true; - } - } - for (var ny = 0; ny < height; ny++) { - var currloc = x + "," + ny; - if (ny != y) { - damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = type[currloc] || {}; - type[currloc]["激光伤害"] = true; - } - } - } - - // 捕捉 - // 如果要防止捕捉效果,可以直接简单的将 flag:no_ambush 设为true - if (enemy && core.enemys.hasSpecial(enemy.special, 27) && !core.hasFlag("no_ambush")) { - var scan = enemy.zoneSquare ? core.utils.scan2 : core.utils.scan; - // 给周围格子加上【捕捉】记号 - for (var dir in scan) { - var nx = x + scan[dir].x, - ny = y + scan[dir].y, - currloc = nx + "," + ny; - if (nx < 0 || nx >= width || ny < 0 || ny >= height || (core.utils.scan[dir] && !core.canMoveHero(x, y, dir, floorId))) continue; - ambush[currloc] = (ambush[currloc] || []).concat([ - [x, y, id, dir] - ]); - } - } - - // 夹击;在这里提前计算所有可能的夹击点,具体计算逻辑在下面 - // 如果要防止夹击伤害,可以简单的将 flag:no_betweenAttack 设为true - if (enemy && core.enemys.hasSpecial(enemy.special, 16) && !core.hasFlag('no_betweenAttack')) { - for (var dir in core.utils.scan) { - var nx = x + core.utils.scan[dir].x, - ny = y + core.utils.scan[dir].y, - currloc = nx + "," + ny; - if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; - betweenAttackLocs[currloc] = true; - } - } - - // 检查地图范围类技能 - var specialFlag = core.getSpecialFlag(enemy); - if (specialFlag & 1) needCache = true; - if (core.status.event.id == 'viewMaps') needCache = true; - if ((core.status.event.id == 'book' || core.status.event.id == 'bool-detail') && core.status.event.ui) needCache = true; - } - - // 对每个可能的夹击点计算夹击伤害 - for (var loc in betweenAttackLocs) { - var xy = loc.split(","), - x = parseInt(xy[0]), - y = parseInt(xy[1]); - // 夹击怪物的ID - var enemyId1 = null, - enemyId2 = null; - // 检查左右夹击 - var leftBlock = blocks[(x - 1) + "," + y], - rightBlock = blocks[(x + 1) + "," + y]; - var leftId = core.getFaceDownId(leftBlock), - rightId = core.getFaceDownId(rightBlock); - if (leftBlock && !leftBlock.disable && rightBlock && !rightBlock.disable && leftId == rightId) { - if (core.hasSpecial(leftId, 16)) - enemyId1 = leftId; - } - // 检查上下夹击 - var topBlock = blocks[x + "," + (y - 1)], - bottomBlock = blocks[x + "," + (y + 1)]; - var topId = core.getFaceDownId(topBlock), - bottomId = core.getFaceDownId(bottomBlock); - if (topBlock && !topBlock.disable && bottomBlock && !bottomBlock.disable && topId == bottomId) { - if (core.hasSpecial(topId, 16)) - enemyId2 = topId; - } - - if (enemyId1 != null || enemyId2 != null) { - var leftHp = core.status.hero.hp - (damage[loc] || 0); - if (leftHp > 1) { - // 夹击伤害值 - var value = Math.floor(leftHp / 2); - // 是否不超过怪物伤害值 - if (core.flags.betweenAttackMax) { - var enemyDamage1 = core.getDamage(enemyId1, x, y, floorId); - if (enemyDamage1 != null && enemyDamage1 < value) - value = enemyDamage1; - var enemyDamage2 = core.getDamage(enemyId2, x, y, floorId); - if (enemyDamage2 != null && enemyDamage2 < value) - value = enemyDamage2; - } - if (value > 0) { - damage[loc] = (damage[loc] || 0) + value; - type[loc] = type[loc] || {}; - type[loc]["夹击伤害"] = true; - } - } - } - } - - // 取消注释下面这一段可以让护盾抵御阻激夹域伤害 - /* - for (var loc in damage) { - damage[loc] = Math.max(0, damage[loc] - core.getRealStatus('mdef')); - } - */ - - core.flags.canGoDeadZone = canGoDeadZone; - core.status.checkBlock = { - damage: damage, - type: type, - repulse: repulse, - ambush: ambush, - needCache: needCache, - cache: {} // clear cache - }; -}, - "moveOneStep": function (callback) { - // 勇士每走一步后执行的操作。callback为行走完毕后的回调 - // 这个函数执行在“刚走完”的时候,即还没有检查该点的事件和领域伤害等。 - // 请注意:瞬间移动不会执行该函数。如果要控制能否瞬间移动有三种方法: - // 1. 将全塔属性中的cannotMoveDirectly这个开关勾上,即可在全塔中全程禁止使用瞬移。 - // 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。 - // 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。 - - // 增加步数 - core.status.hero.steps++; - // 更新跟随者状态,并绘制 - core.updateFollowers(); - core.drawHero(); - // 检查中毒状态的扣血和死亡 - if (core.hasFlag('poison')) { - core.status.hero.statistics.poisonDamage += core.values.poisonDamage; - core.status.hero.hp -= core.values.poisonDamage; - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - return; - } else { - core.updateStatusBar(); - } - } - - // 从v2.7开始,每一步行走不会再刷新状态栏。 - // 如果有特殊要求(如每走一步都加buff之类),可手动取消注释下面这一句: - // core.updateStatusBar(true); - - // 检查自动事件 - core.checkAutoEvents(); - - // ------ 检查目标点事件 ------ // - // 无事件的道具(如血瓶)需要优先于阻激夹域判定 - var nowx = core.getHeroLoc('x'), - nowy = core.getHeroLoc('y'); - var block = core.getBlock(nowx, nowy); - var hasTrigger = false; - if (block != null && block.event.trigger == 'getItem' && - !core.floors[core.status.floorId].afterGetItem[nowx + "," + nowy]) { - hasTrigger = true; - core.trigger(nowx, nowy, callback); - } - // 执行目标点的阻激夹域事件 - core.checkBlock(); - - // 执行目标点的script和事件 - if (!hasTrigger) - core.trigger(nowx, nowy, callback); - - // 检查该点是否是滑冰 - if (core.onSki()) { - // 延迟到事件最后执行,因为这之前可能有阻激夹域动画 - core.insertAction({ "type": "moveAction" }, null, null, null, true); - } - - // ------ 检查目标点事件 END ------ // - - // 如需强行终止行走可以在这里条件判定: - // core.stopAutomaticRoute(); -}, - "moveDirectly": function (x, y, ignoreSteps) { - // 瞬间移动;x,y为要瞬间移动的点;ignoreSteps为减少的步数,可能之前已经被计算过 - // 返回true代表成功瞬移,false代表没有成功瞬移 - - // 判定能否瞬移到该点 - if (ignoreSteps == null) ignoreSteps = core.canMoveDirectly(x, y); - if (ignoreSteps >= 0) { - // 中毒也允许瞬移 - if (core.hasFlag('poison')) { - var damage = ignoreSteps * core.values.poisonDamage; - if (damage >= core.status.hero.hp) return false; - core.status.hero.statistics.poisonDamage += damage; + // 扣减体力值并记录统计数据 core.status.hero.hp -= damage; + core.status.hero.statistics.battleDamage += damage; + core.status.hero.statistics.battle++; + + // 计算当前怪物的支援怪物 + var guards = []; + if (x != null && y != null) { + guards = core.getFlag("__guards__" + x + "_" + y, []); + core.removeFlag("__guards__" + x + "_" + y); + } + + // 获得金币 + var money = guards.reduce(function (curr, g) { + return curr + core.material.enemys[g[2]].money; + }, core.getEnemyValue(enemy, "money", x, y)); + if (core.hasItem('coin')) money *= 2; // 幸运金币:双倍 + if (core.hasFlag('curse')) money = 0; // 诅咒效果 + core.status.hero.money += money; + core.status.hero.statistics.money += money; + + // 获得经验 + var exp = guards.reduce(function (curr, g) { + return curr + core.material.enemys[g[2]].exp; + }, core.getEnemyValue(enemy, "exp", x, y)); + if (core.hasFlag('curse')) exp = 0; + core.status.hero.exp += exp; + core.status.hero.statistics.exp += exp; + + var hint = "打败 " + core.getEnemyValue(enemy, "name", x, y); + if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) + hint += ',' + core.getStatusLabel('money') + '+' + money; // hint += ",金币+" + money; + if (core.flags.statusBarItems.indexOf('enableExp') >= 0) + hint += ',' + core.getStatusLabel('exp') + '+' + exp; // hint += ",经验+" + exp; + core.drawTip(hint, enemy.id); + + // 中毒 + if (core.enemys.hasSpecial(special, 12)) { + core.triggerDebuff('get', 'poison'); + } + // 衰弱 + if (core.enemys.hasSpecial(special, 13)) { + core.triggerDebuff('get', 'weak'); + } + // 诅咒 + if (core.enemys.hasSpecial(special, 14)) { + core.triggerDebuff('get', 'curse'); + } + // 仇恨怪物将仇恨值减半 + if (core.enemys.hasSpecial(special, 17)) { + core.setFlag('hatred', Math.floor(core.getFlag('hatred', 0) / 2)); + } + // 自爆 + if (core.enemys.hasSpecial(special, 19)) { + core.status.hero.statistics.battleDamage += core.status.hero.hp - 1; + core.status.hero.hp = 1; + } + // 退化 + if (core.enemys.hasSpecial(special, 21)) { + core.status.hero.atk -= (enemy.atkValue || 0); + core.status.hero.def -= (enemy.defValue || 0); + if (core.status.hero.atk < 0) core.status.hero.atk = 0; + if (core.status.hero.def < 0) core.status.hero.def = 0; + } + // 增加仇恨值 + core.setFlag('hatred', core.getFlag('hatred', 0) + core.values.hatred); + + // 战后的技能处理,比如扣除魔力值 + if (core.flags.statusBarItems.indexOf('enableSkill') >= 0) { + // 检测当前开启的技能类型 + var skill = core.getFlag('skill', 0); + if (skill == 1) { // 技能1:二倍斩 + core.status.hero.mana -= 5; // 扣除5点魔力值 + } + // 关闭技能 + core.setFlag('skill', 0); + core.setFlag('skillName', '无'); + } + + + // 事件的处理 + var todo = []; + + // 加点事件 + var point = guards.reduce(function (curr, g) { + return curr + core.material.enemys[g[2]].point; + }, core.getEnemyValue(enemy, "point", x, y)) || 0; + if (core.flags.enableAddPoint && point > 0) { + core.push(todo, [{ "type": "insert", "name": "加点事件", "args": [point] }]); + } + + // 战后事件 + if (core.status.floorId != null) { + core.push(todo, core.floors[core.status.floorId].afterBattle[x + "," + y]); + } + core.push(todo, enemy.afterBattle); + + // 在这里增加其他的自定义事件需求 + /* + if (enemyId=='xxx') { + core.push(todo, [ + {"type": "...", ...}, + ]); + } + */ + + // 如果事件不为空,将其插入 + if (todo.length > 0) core.insertAction(todo, x, y); + + // 删除该点设置的怪物信息 + delete ((flags.enemyOnPoint || {})[core.status.floorId] || {})[x + "," + y]; + + // 因为removeBlock和hideBlock都会刷新状态栏,因此将删除部分移动到这里并保证刷新只执行一次,以提升效率 + if (core.getBlock(x, y) != null) { + // 检查是否是重生怪物;如果是则仅隐藏不删除 + if (core.hasSpecial(enemy.special, 23)) { + core.hideBlock(x, y); + } else { + core.removeBlock(x, y); + } + } else { + core.updateStatusBar(); + } + + // 如果已有事件正在处理中 + if (core.status.event.id == null) + core.continueAutomaticRoute(); + else + core.clearContinueAutomaticRoute(); + + }, + "afterOpenDoor": function (doorId, x, y) { + // 开一个门后触发的事件 + + var todo = []; + // 检查该点的开门后事件 + if (core.status.floorId) { + core.push(todo, core.floors[core.status.floorId].afterOpenDoor[x + "," + y]); + } + // 检查批量开门事件 + var door = core.getBlockById(doorId); + if (door && door.event.doorInfo) { + core.push(todo, door.event.doorInfo.afterOpenDoor); + } + + if (todo.length > 0) core.insertAction(todo, x, y); + + if (core.status.event.id == null) + core.continueAutomaticRoute(); + else + core.clearContinueAutomaticRoute(); + }, + "afterGetItem": function (itemId, x, y, isGentleClick) { + // 获得一个道具后触发的事件 + // itemId:获得的道具ID;x和y是该道具所在的坐标 + // isGentleClick:是否是轻按触发的 + if (itemId.endsWith('Potion') && core.material.items[itemId].cls == 'items') + core.playSound('回血'); + else if (itemId.endsWith('Gem') && core.material.items[itemId].cls == 'items') + core.playSound('宝石') + else + core.playSound('获得道具'); + + var todo = []; + // 检查该点的获得道具后事件。 + if (core.status.floorId == null) return; + var event = core.floors[core.status.floorId].afterGetItem[x + "," + y]; + if (event && (event instanceof Array || !isGentleClick || !event.disableOnGentleClick)) { + core.unshift(todo, event); + } + + if (todo.length > 0) core.insertAction(todo, x, y); + }, + "afterPushBox": function () { + // 推箱子后的事件 + if (core.searchBlock('box').length == 0) { + // 可以通过if语句来进行开门操作 + /* + if (core.status.floorId=='xxx') { // 在某个楼层 + core.insertAction([ // 插入一条事件 + {"type": "openDoor", "loc": [x,y]} // 开门 + ]) + } + */ + } } + }, + "enemys": { + "getSpecials": function () { + // 获得怪物的特殊属性,每一行定义一个特殊属性。 + // 分为五项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述 + // 第四项为该特殊属性的颜色,可以写十六进制 #RRGGBB 或者 [r,g,b,a] 四元数组 + // 第五项为该特殊属性的标记;目前 1 代表是地图类技能(需要进行遍历全图) + // 名字和描述可以直接写字符串,也可以写个function将怪物传进去 + return [ + [1, "先攻", "怪物首先攻击", "#ffcc33"], + [2, "魔攻", "怪物无视角色的防御", "#bbb0ff"], + [3, "坚固", "怪物防御不小于角色攻击-1", "#c0b088"], + [4, "2连击", "怪物每回合攻击2次", "#ffee77"], + [5, "3连击", "怪物每回合攻击3次", "#ffee77"], + [6, function (enemy) { return (enemy.n || '') + "连击"; }, function (enemy) { return "怪物每回合攻击" + (enemy.n || 4) + "次"; }, "#ffee77"], + [7, "破甲", function (enemy) { return "战斗前,怪物附加角色防御的" + Math.floor(100 * (enemy.defValue || core.values.breakArmor || 0)) + "%作为伤害"; }, "#88c0ff"], + [8, "反击", function (enemy) { return "战斗时,怪物每回合附加角色攻击的" + Math.floor(100 * (enemy.atkValue || core.values.counterAttack || 0)) + "%作为伤害,无视角色防御"; }, "#ffaa44"], + [9, "净化", function (enemy) { return "战斗前,怪物附加角色护盾的" + (enemy.n || core.values.purify) + "倍作为伤害"; }, "#80eed6"], + [10, "模仿", "怪物的攻防和角色攻防相等", "#b0c0dd"], + [11, "吸血", function (enemy) { return "战斗前,怪物首先吸取角色的" + Math.floor(100 * enemy.value || 0) + "%生命(约" + Math.floor((enemy.value || 0) * core.getStatus('hp')) + "点)作为伤害" + (enemy.add ? ",并把伤害数值加到自身生命上" : ""); }, "#dd4448"], + [12, "中毒", "战斗后,角色陷入中毒状态,每一步损失生命" + core.values.poisonDamage + "点", "#99ee88"], + [13, "衰弱", "战斗后,角色陷入衰弱状态,攻防暂时下降" + (core.values.weakValue >= 1 ? core.values.weakValue + "点" : parseInt(core.values.weakValue * 100) + "%"), "#f0bbcc"], + [14, "诅咒", "战斗后,角色陷入诅咒状态,战斗无法获得金币和经验", "#bbeef0"], + [15, "领域", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "范围内" + (enemy.range || 1) + "格时自动减生命" + (enemy.value || 0) + "点"; }, "#c677dd"], + [16, "夹击", "经过两只相同的怪物中间,角色生命值变成一半", "#bb99ee"], + [17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害;战斗后,释放一半的仇恨值。(每杀死一个怪物获得" + (core.values.hatred || 0) + "点仇恨值)", "#b0b666"], + [18, "阻击", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时自动减生命" + (enemy.value || 0) + "点,同时怪物后退一格"; }, "#8888e6"], + [19, "自爆", "战斗后角色的生命值变成1", "#ff6666"], + [20, "无敌", "角色无法打败怪物,除非拥有十字架", "#aaaaaa"], + [21, "退化", function (enemy) { return "战斗后角色永久下降" + (enemy.atkValue || 0) + "点攻击和" + (enemy.defValue || 0) + "点防御"; }], + [22, "固伤", function (enemy) { return "战斗前,怪物对角色造成" + (enemy.damage || 0) + "点固定伤害,未开启负伤时无视角色护盾。"; }, "#ff9977"], + [23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现", "#a0e0ff"], + [24, "激光", function (enemy) { return "经过怪物同行或同列时自动减生命" + (enemy.value || 0) + "点"; }, "#dda0dd"], + [25, "光环", function (enemy) { return (enemy.range != null ? ((enemy.zoneSquare ? "该怪物九宫格" : "该怪物十字") + enemy.range + "格范围内") : "同楼层所有") + "怪物生命提升" + (enemy.value || 0) + "%,攻击提升" + (enemy.atkValue || 0) + "%,防御提升" + (enemy.defValue || 0) + "%," + (enemy.add ? "可叠加" : "不可叠加"); }, "#e6e099", 1], + [26, "支援", "当周围一圈的怪物受到攻击时将上前支援,并组成小队战斗。", "#77c0b6", 1], + [27, "捕捉", function (enemy) { return "当走到怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时会强制进行战斗。"; }, "#c0ddbb"] + ]; + }, + "getEnemyInfo": function (enemy, hero, x, y, floorId) { + // 获得某个怪物变化后的数据;该函数将被伤害计算和怪物手册使用 + // 例如:坚固、模仿、仿攻等等 + // + // 参数说明: + // enemy:该怪物信息 + // hero_hp,hero_atk,hero_def,hero_mdef:勇士的生命攻防护盾数据 + // x,y:该怪物的坐标(查看手册和强制战斗时为undefined) + // floorId:该怪物所在的楼层 + // 后面三个参数主要是可以在光环等效果上可以适用(也可以按需制作部分范围光环效果) + floorId = floorId || core.status.floorId; + var hero_hp = core.getRealStatusOrDefault(hero, 'hp'), + hero_atk = core.getRealStatusOrDefault(hero, 'atk'), + hero_def = core.getRealStatusOrDefault(hero, 'def'), + hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'); - core.clearMap('hero'); - // 获得勇士最后的朝向 - var lastDirection = core.status.route[core.status.route.length - 1]; - if (['left', 'right', 'up', 'down'].indexOf(lastDirection) >= 0) - core.setHeroLoc('direction', lastDirection); - // 设置坐标,并绘制 - core.control._moveDirectyFollowers(x, y); - core.status.hero.loc.x = x; - core.status.hero.loc.y = y; - core.drawHero(); - // 记录录像 - core.status.route.push("move:" + x + ":" + y); - // 统计信息 - core.status.hero.statistics.moveDirectly++; - core.status.hero.statistics.ignoreSteps += ignoreSteps; - if (core.hasFlag('poison')) { - core.updateStatusBar(); + var mon_hp = core.getEnemyValue(enemy, 'hp', x, y, floorId), + mon_atk = core.getEnemyValue(enemy, 'atk', x, y, floorId), + mon_def = core.getEnemyValue(enemy, 'def', x, y, floorId), + mon_special = core.getEnemyValue(enemy, 'special', x, y, floorId); + var mon_money = core.getEnemyValue(enemy, 'money', x, y, floorId), + mon_exp = core.getEnemyValue(enemy, 'exp', x, y, floorId), + mon_point = core.getEnemyValue(enemy, 'point', x, y, floorId); + // 模仿 + if (core.hasSpecial(mon_special, 10)) { + mon_atk = hero_atk; + mon_def = hero_def; + } + // 坚固 + if (core.hasSpecial(mon_special, 3) && mon_def < hero_atk - 1) { + mon_def = hero_atk - 1; + } + + var guards = []; + + // 光环和支援检查 + if (!core.status.checkBlock) core.status.checkBlock = {}; + + if (core.status.checkBlock.needCache) { + // 从V2.5.4开始,对光环效果增加缓存,以解决多次重复计算的问题,从而大幅提升运行效率。 + var hp_buff = 0, + atk_buff = 0, + def_buff = 0; + // 已经计算过的光环怪ID列表,用于判定叠加 + var usedEnemyIds = {}; + // 检查光环和支援的缓存 + var index = x != null && y != null ? (x + "," + y) : floorId; + if (!core.status.checkBlock.cache) core.status.checkBlock.cache = {}; + var cache = core.status.checkBlock.cache[index]; + if (!cache) { + // 没有该点的缓存,则遍历每个图块 + core.extractBlocks(floorId); + core.status.maps[floorId].blocks.forEach(function (block) { + if (!block.disable) { + // 获得该图块的ID + var id = block.event.id, + enemy = core.material.enemys[id]; + // 检查【光环】技能,数字25 + if (enemy && core.hasSpecial(enemy.special, 25)) { + // 检查是否是范围光环 + var inRange = enemy.range == null; + if (enemy.range != null && x != null && y != null) { + var dx = Math.abs(block.x - x), + dy = Math.abs(block.y - y); + // 检查十字和九宫格光环 + if (dx + dy <= enemy.range) inRange = true; + if (enemy.zoneSquare && dx <= enemy.range && dy <= enemy.range) inRange = true; + } + // 检查是否可叠加 + if (inRange && (enemy.add || !usedEnemyIds[enemy.id])) { + hp_buff += enemy.value || 0; + atk_buff += enemy.atkValue || 0; + def_buff += enemy.defValue || 0; + usedEnemyIds[enemy.id] = true; + } + } + // 检查【支援】技能,数字26 + if (enemy && core.hasSpecial(enemy.special, 26) && + // 检查支援条件,坐标存在,距离为1,且不能是自己 + // 其他类型的支援怪,比如十字之类的话.... 看着做是一样的 + x != null && y != null && Math.abs(block.x - x) <= 1 && Math.abs(block.y - y) <= 1 && !(x == block.x && y == block.y)) { + // 记录怪物的x,y,ID + guards.push([block.x, block.y, id]); + } + + // TODO:如果有其他类型光环怪物在这里仿照添加检查 + // 注:新增新的类光环属性(需要遍历全图的)需要在特殊属性定义那里的第五项写1,参见光环和支援的特殊属性定义。 + } + }); + + core.status.checkBlock.cache[index] = { "hp_buff": hp_buff, "atk_buff": atk_buff, "def_buff": def_buff, "guards": guards }; + } else { + // 直接使用缓存数据 + hp_buff = cache.hp_buff; + atk_buff = cache.atk_buff; + def_buff = cache.def_buff; + guards = cache.guards; + } + + // 增加比例;如果要增加数值可以直接在这里修改 + mon_hp *= (1 + hp_buff / 100); + mon_atk *= (1 + atk_buff / 100); + mon_def *= (1 + def_buff / 100); + } + + // TODO:可以在这里新增其他的怪物数据变化 + // 比如仿攻(怪物攻击不低于勇士攻击): + // if (core.hasSpecial(mon_special, 27) && mon_atk < hero_atk) { + // mon_atk = hero_atk; + // } + // 也可以按需增加各种自定义内容 + + return { + "hp": Math.floor(mon_hp), + "atk": Math.floor(mon_atk), + "def": Math.floor(mon_def), + "money": Math.floor(mon_money), + "exp": Math.floor(mon_exp), + "point": Math.floor(mon_point), + "special": mon_special, + "guards": guards, // 返回支援情况 + }; + }, + "getDamageInfo": function (enemy, hero, x, y, floorId) { + // 获得战斗伤害信息(实际伤害计算函数) + // + // 参数说明: + // enemy:该怪物信息 + // hero:勇士的当前数据;如果对应项不存在则会从core.status.hero中取。 + // x,y:该怪物的坐标(查看手册和强制战斗时为undefined) + // floorId:该怪物所在的楼层 + // 后面三个参数主要是可以在光环等效果上可以适用 + floorId = floorId || core.status.floorId; + + var hero_hp = core.getRealStatusOrDefault(hero, 'hp'), + hero_atk = core.getRealStatusOrDefault(hero, 'atk'), + hero_def = core.getRealStatusOrDefault(hero, 'def'), + hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'), + origin_hero_hp = core.getStatusOrDefault(hero, 'hp'), + origin_hero_atk = core.getStatusOrDefault(hero, 'atk'), + origin_hero_def = core.getStatusOrDefault(hero, 'def'); + + // 勇士的负属性都按0计算 + hero_hp = Math.max(0, hero_hp); + hero_atk = Math.max(0, hero_atk); + hero_def = Math.max(0, hero_def); + hero_mdef = Math.max(0, hero_mdef); + + // 怪物的各项数据 + // 对坚固模仿等处理扔到了脚本编辑-getEnemyInfo之中 + var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y, floorId); + var mon_hp = enemyInfo.hp, + mon_atk = enemyInfo.atk, + mon_def = enemyInfo.def, + mon_special = enemyInfo.special; + + // 技能的处理 + if (core.getFlag('skill', 0) == 1) { // 开启了技能1:二倍斩 + hero_atk *= 2; // 计算时攻击力翻倍 + } + + // 如果是无敌属性,且勇士未持有十字架 + if (core.hasSpecial(mon_special, 20) && !core.hasItem("cross")) + return null; // 不可战斗 + + // 战前造成的额外伤害(可被护盾抵消) + var init_damage = 0; + + // 吸血 + if (core.hasSpecial(mon_special, 11)) { + var vampire_damage = hero_hp * enemy.value; + + // 如果有神圣盾免疫吸血等可以在这里写 + // 也可以用hasItem和hasEquip来判定装备 + // if (core.hasFlag('shield5')) vampire_damage = 0; + + vampire_damage = Math.floor(vampire_damage) || 0; + // 加到自身 + if (enemy.add) // 如果加到自身 + mon_hp += vampire_damage; + + init_damage += vampire_damage; + } + + // 每回合怪物对勇士造成的战斗伤害 + var per_damage = mon_atk - hero_def; + // 魔攻:战斗伤害就是怪物攻击力 + if (core.hasSpecial(mon_special, 2)) per_damage = mon_atk; + // 战斗伤害不能为负值 + if (per_damage < 0) per_damage = 0; + + // 2连击 & 3连击 & N连击 + if (core.hasSpecial(mon_special, 4)) per_damage *= 2; + if (core.hasSpecial(mon_special, 5)) per_damage *= 3; + if (core.hasSpecial(mon_special, 6)) per_damage *= (enemy.n || 4); + + // 每回合的反击伤害;反击是按照勇士的攻击次数来计算回合 + var counterDamage = 0; + if (core.hasSpecial(mon_special, 8)) + counterDamage += Math.floor((enemy.atkValue || core.values.counterAttack) * hero_atk); + + // 先攻 + if (core.hasSpecial(mon_special, 1)) init_damage += per_damage; + + // 破甲 + if (core.hasSpecial(mon_special, 7)) + init_damage += Math.floor((enemy.defValue || core.values.breakArmor) * hero_def); + + // 净化 + if (core.hasSpecial(mon_special, 9)) + init_damage += Math.floor((enemy.n || core.values.purify) * hero_mdef); + + // 勇士每回合对怪物造成的伤害 + var hero_per_damage = Math.max(hero_atk - mon_def, 0); + + // 如果没有破防,则不可战斗 + if (hero_per_damage <= 0) return null; + + // 勇士的攻击回合数;为怪物生命除以每回合伤害向上取整 + var turn = Math.ceil(mon_hp / hero_per_damage); + + // ------ 支援 ----- // + // 这个递归最好想明白为什么,flag:__extraTurn__是怎么用的 + var guards = core.getFlag("__guards__" + x + "_" + y, enemyInfo.guards); + var guard_before_current_enemy = false; // ------ 支援怪是先打(true)还是后打(false)? + turn += core.getFlag("__extraTurn__", 0); + if (guards.length > 0) { + if (!guard_before_current_enemy) { // --- 先打当前怪物,记录当前回合数 + core.setFlag("__extraTurn__", turn); + } + // 获得那些怪物组成小队战斗 + for (var i = 0; i < guards.length; i++) { + var gx = guards[i][0], + gy = guards[i][1], + gid = guards[i][2]; + // 递归计算支援怪伤害信息,这里不传x,y保证不会重复调用 + // 这里的mdef传0,因为护盾应该只会被计算一次 + var info = core.enemys.getDamageInfo(core.material.enemys[gid], { hp: origin_hero_hp, atk: origin_hero_atk, def: origin_hero_def, mdef: 0 }); + if (info == null) { // 小队中任何一个怪物不可战斗,直接返回null + core.removeFlag("__extraTurn__"); + return null; + } + // 已经进行的回合数 + core.setFlag("__extraTurn__", info.turn); + init_damage += info.damage; + } + if (guard_before_current_enemy) { // --- 先打支援怪物,增加当前回合数 + turn += core.getFlag("__extraTurn__", 0); + } + } + core.removeFlag("__extraTurn__"); + // ------ 支援END ------ // + + // 最终伤害:初始伤害 + 怪物对勇士造成的伤害 + 反击伤害 + var damage = init_damage + (turn - 1) * per_damage + turn * counterDamage; + // 再扣去护盾 + damage -= hero_mdef; + + // 检查是否允许负伤 + if (!core.flags.enableNegativeDamage) + damage = Math.max(0, damage); + + // 最后处理仇恨和固伤(因为这两个不能被护盾减伤) + if (core.hasSpecial(mon_special, 17)) { // 仇恨 + damage += core.getFlag('hatred', 0); + } + if (core.hasSpecial(mon_special, 22)) { // 固伤 + damage += enemy.damage || 0; + } + + return { + "mon_hp": Math.floor(mon_hp), + "mon_atk": Math.floor(mon_atk), + "mon_def": Math.floor(mon_def), + "init_damage": Math.floor(init_damage), + "per_damage": Math.floor(per_damage), + "hero_per_damage": Math.floor(hero_per_damage), + "turn": Math.floor(turn), + "damage": Math.floor(damage) + }; } - core.checkRouteFolding(); - return true; - } - return false; -}, - "parallelDo": function (timestamp) { - // 并行事件处理,可以在这里写任何需要并行处理的脚本或事件 - // 该函数将被系统反复执行,每次执行间隔视浏览器或设备性能而定,一般约为16.6ms一次 - // 参数timestamp为“从游戏资源加载完毕到当前函数执行时”的时间差,以毫秒为单位 + }, + "actions": { + "onKeyUp": function (keyCode, altKey) { + // 键盘按键处理,可以在这里自定义快捷键列表 + // keyCode:当前按键的keyCode(每个键的keyCode自行百度) + // altKey:Alt键是否被按下,为true代表同时按下了Alt键 + // 可以在这里任意增加或编辑每个按键的行为 - // 检查当前是否处于游戏开始状态 - if (!core.isPlaying()) return; + // 如果处于正在行走状态,则不处理 + if (core.isMoving()) + return; - // 执行当前楼层的并行事件处理 - if (core.status.floorId) { - try { - eval(core.floors[core.status.floorId].parallelDo); - } catch (e) { - main.log(e); + // Alt+0~9,快捷换上套装 + if (altKey && keyCode >= 48 && keyCode <= 57) { + core.items.quickLoadEquip(keyCode - 48); + return; + } + + // 根据keyCode值来执行对应操作 + switch (keyCode) { + case 27: // ESC:打开菜单栏 + core.openSettings(true); + break; + case 88: // X:使用怪物手册 + core.openBook(true); + break; + case 71: // G:使用楼传器 + core.useFly(true); + break; + case 65: // A:读取自动存档(回退) + core.doSL("autoSave", "load"); + break; + case 87: // W:撤销回退 + core.doSL("autoSave", "reload"); + break; + case 83: // S:存档 + core.save(true); + break; + case 68: // D:读档 + core.load(true); + break; + case 69: // E:打开光标 + core.ui._drawCursor(); + break; + case 84: // T:打开道具栏 + core.openToolbox(true); + break; + case 81: // Q:打开装备栏 + core.openEquipbox(true); + break; + case 90: // Z:转向 + core.turnHero(); + break; + case 86: // V:打开快捷商店列表 + core.openQuickShop(true); + break; + case 32: // SPACE:轻按 + core.getNextItem(); + break; + case 82: // R:回放录像 + core.ui._drawReplay(); + break; + case 33: + case 34: // PgUp/PgDn:浏览地图 + core.ui._drawViewMaps(); + break; + case 66: // B:打开数据统计 + core.ui._drawStatistics(); + break; + case 72: // H:打开帮助页面 + core.ui._drawHelp(); + break; + case 77: // M:打开存档笔记 + core.actions._clickNotes_show(); + break; + case 78: // N:重新开始 + core.confirmRestart(); + break; + case 79: // O:查看工程 + core.actions._clickGameInfo_openProject(); + break; + case 80: // P:游戏主页 + core.actions._clickGameInfo_openComments(); + break; + case 49: // 快捷键1: 破 + if (core.hasItem('pickaxe')) { + core.status.route.push("key:49"); // 将按键记在录像中 + core.useItem('pickaxe', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 + } + break; + case 50: // 快捷键2: 炸 + if (core.hasItem('bomb')) { + core.status.route.push("key:50"); // 将按键记在录像中 + core.useItem('bomb', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 + } + break; + case 51: // 快捷键3: 飞 + if (core.hasItem('centerFly')) { + core.ui._drawCenterFly(); + } + break; + case 52: // 快捷键4:破冰/冰冻/地震/上下楼器/... 其他道具依次判断 + { + var list = ["icePickaxe", "freezeBadge", "earthquake", "upFly", "downFly", "jumpShoes", "lifeWand", "poisonWine", "weakWine", "curseWine", "superWine"]; + for (var i = 0; i < list.length; i++) { + var itemId = list[i]; + if (core.canUseItem(itemId)) { + core.status.route.push("key:52"); + core.useItem(itemId, true); + break; + } + } + } + break; + case 53: // 5:读取自动存档(回退),方便手机版操作 + core.doSL("autoSave", "load"); + break; + case 54: // 6:撤销回退,方便手机版操作 + core.doSL("autoSave", "reload"); + break; + case 55: // 快捷键7:绑定为轻按,方便手机版操作 + core.getNextItem(); + break; + case 118: // F7:开启debug模式 + core.debug(); + break; + case 70: // F:开启技能“二倍斩” + // 检测是否拥有“二倍斩”这个技能道具 + if (core.hasItem('skill1')) { + core.status.route.push("key:70"); + core.useItem('skill1', true); + } + break; + // 在这里可以任意新增或编辑已有的快捷键内容 + /* + case 0: // 使用该按键的keyCode + // 还可以再判定altKey是否被按下,即 if (altKey) { ... + + // ... 在这里写你要执行脚本 + // **强烈建议所有新增的自定义快捷键均能给个对应的道具可点击,以方便手机端的行为** + if (core.hasItem('...')) { + core.status.route.push("key:0"); + core.useItem('...', true); // 增加true代表该使用道具不计入录像 + } + + break; + */ + } + + }, + "onStatusBarClick": function (px, py, vertical) { + // 点击状态栏时触发的事件,仅在自绘状态栏开启时生效 + // px和py为点击的像素坐标 + // vertical为录像播放过程中的横竖屏信息 + // + // 横屏模式下状态栏的画布大小是 129*416 (开启拓展装备栏后是 129*457) + // 竖屏模式下状态栏的画布大小是 416*(32*rows+9) 其中rows为状态栏行数,即全塔属性中statusCanvasRowsOnMobile值 + // 可以使用 _isVertical() 来判定当前是否是竖屏模式 + + // 判定当前是否是竖屏模式。录像播放过程中可能会记录当时的横竖屏信息以覆盖。 + var _isVertical = function () { + if (core.isReplaying() && vertical != null) return vertical; + return core.domStyle.isVertical; + } + + // 如果正在执行事件,则忽略 + if (core.status.lockControl) return; + // 如果当前正在行走,则忽略;也可以使用 core.waitHeroToStop(callback) 来停止行走再回调执行脚本 + if (core.isMoving()) return; + + // 判定px和py来执行自己的脚本内容.... 注意横竖屏 + // console.log("onStatusBarClick: ", px, py, _isVertical()); + + // 样例一:点击某个区域后使用一个道具 + /* + if (core.hasItem("pickaxe")) { + if (_isVertical()) { + // 竖屏模式下 + if (px >= 200 && px <= 250 && py >= 50 && py <= 100) { + core.useItem("pickaxe"); + } + } else { + // 横屏模式下 + if (px >= 50 && px <= 100 && py >= 200 && py <= 250) { + core.useItem("pickaxe"); + } + } + } + */ + + // 样例二:点击某个区域后执行一段公共事件或脚本 + /* + if (core.hasFlag("xxx")) { + if (_isVertical()) { + // 竖屏模式下 + if (px >= 200 && px <= 250 && py >= 50 && py <= 100) { + // 记录点击坐标。这里的1代表此时是竖屏! + core.status.route.push("click:1:" + px + ":" + py); + + // 可以插入公共事件 / 普通事件 / 执行一段脚本(如打开自绘UI或增减flag) + core.insertCommonEvent("道具商店"); + // core.insertAction(["一段事件"]); + // core.openItemShop("shop1"); + } + } else { + // 横屏模式下 + if (px >= 50 && px <= 100 && py >= 200 && py <= 250) { + // 记录点击坐标。这里的0代表此时是横屏! + core.status.route.push("click:0:" + px + ":" + py); + + // 可以插入公共事件 / 普通事件 / 执行一段脚本(如打开自绘UI或增减flag) + core.insertCommonEvent("道具商店"); + // core.insertAction(["一段事件"]); + // core.openItemShop("shop1"); + } + } + } + */ + + } + }, + "control": { + "saveData": function () { + // 存档操作,此函数应该返回“具体要存档的内容” + + // 差异化存储values + var values = {}; + for (var key in core.values) { + if (!core.same(core.values[key], core.data.values[key])) + values[key] = core.clone(core.values[key]); + } + + // 要存档的内容 + var data = { + 'floorId': core.status.floorId, + 'hero': core.clone(core.status.hero), + 'hard': core.status.hard, + 'maps': core.clone(core.maps.saveMap()), + 'route': core.encodeRoute(core.status.route), + 'values': values, + 'version': core.firstData.version, + 'guid': core.getGuid(), + "time": new Date().getTime() + }; + + return data; + }, + "loadData": function (data, callback) { + // 读档操作;从存储中读取了内容后的行为 + + // 重置游戏和路线 + core.resetGame(data.hero, data.hard, data.floorId, core.maps.loadMap(data.maps, null, data.hero.flags), data.values); + core.status.route = core.decodeRoute(data.route); + core.control._bindRoutePush(); + // 文字属性,全局属性 + core.status.textAttribute = core.getFlag('textAttribute', core.status.textAttribute); + var toAttribute = core.getFlag('globalAttribute', core.status.globalAttribute); + if (!core.same(toAttribute, core.status.globalAttribute)) { + core.status.globalAttribute = toAttribute; + core.resize(); + } + // 重置音量 + core.events.setVolume(core.getFlag("__volume__", 1), 0); + // 加载勇士图标 + var icon = core.status.hero.image; + icon = core.getMappedName(icon); + if (core.material.images.images[icon]) { + core.material.images.hero = core.material.images.images[icon]; + core.material.icons.hero.width = core.material.images.images[icon].width / 4; + core.material.icons.hero.height = core.material.images.images[icon].height / 4; + } + core.setFlag('__fromLoad__', true); + + // TODO:增加自己的一些读档处理 + + // 切换到对应的楼层 + core.changeFloor(data.floorId, null, data.hero.loc, 0, function () { + // TODO:可以在这里设置读档后播放BGM + if (core.hasFlag("__bgm__")) { // 持续播放 + core.playBgm(core.getFlag("__bgm__")); + } + + core.removeFlag('__fromLoad__'); + if (callback) callback(); + }); + }, + "getStatusLabel": function (name) { + // 返回某个状态英文名的对应中文标签,如atk -> 攻击,def -> 防御等。 + // 请注意此项仅影响 libs/ 下的内容(如绘制怪物手册、数据统计等) + // 自行定义的(比如获得道具效果)中用到的“攻击+3”等需要自己去对应地方修改 + + return { + name: "名称", + lv: "等级", + hpmax: "生命上限", + hp: "生命", + manamax: "魔力上限", + mana: "魔力", + atk: "攻击", + def: "防御", + mdef: "护盾", + money: "金币", + exp: "经验", + point: "加点", + steps: "步数", + }[name] || name; + }, + "triggerDebuff": function (action, type) { + // 毒衰咒效果的获得与解除 + // action:获得还是解除;'get'表示获得,'remove'表示解除 + // type:一个数组表示获得了哪些毒衰咒效果;poison, weak,curse + if (!(type instanceof Array)) type = [type]; + + if (action == 'get') { + if (core.inArray(type, 'poison') && !core.hasFlag("poison")) { + // 获得毒效果 + core.setFlag('poison', true); + } + if (core.inArray(type, 'weak') && !core.hasFlag('weak')) { + // 获得衰效果 + core.setFlag('weak', true); + if (core.values.weakValue >= 1) { + // >=1,直接扣数值 + core.addStatus('atk', -core.values.weakValue); + core.addStatus('def', -core.values.weakValue); + } else { + // <1,扣比例 + core.addBuff('atk', -core.values.weakValue); + core.addBuff('def', -core.values.weakValue); + } + } + if (core.inArray(type, 'curse') && !core.hasFlag('curse')) { + // 获得咒效果 + core.setFlag('curse', true); + } + } else if (action == 'remove') { + var success = false; + if (core.inArray(type, "poison") && core.hasFlag("poison")) { + success = true; + // 移除毒效果 + core.setFlag("poison", false); + } + if (core.inArray(type, "weak") && core.hasFlag("weak")) { + success = true; + // 移除衰效果 + core.setFlag("weak", false); + if (core.values.weakValue >= 1) { + // >=1,直接扣数值 + core.addStatus('atk', core.values.weakValue); + core.addStatus('def', core.values.weakValue); + } else { + // <1,扣比例 + core.addBuff('atk', core.values.weakValue); + core.addBuff('def', core.values.weakValue); + } + } + if (core.inArray(type, "curse") && core.hasFlag("curse")) { + success = true; + // 移除咒效果 + core.setFlag("curse", false); + } + if (success) core.playSound('回血'); + } + }, + "updateStatusBar": function () { + // 更新状态栏 + + // 检查等级 + core.events.checkLvUp(); + + // 检查HP上限 + if (core.flags.statusBarItems.indexOf('enableHPMax') >= 0) { + core.setStatus('hp', Math.min(core.getRealStatus('hpmax'), core.getStatus('hp'))); + } + + // 设置楼层名 + if (core.status.floorId) { + core.setStatusBarInnerHTML('floor', core.status.maps[core.status.floorId].name); + } + + // 设置勇士名字和图标 + core.setStatusBarInnerHTML('name', core.getStatus('name')); + // 设置等级名称 + core.setStatusBarInnerHTML('lv', core.getLvName()); + + // 设置生命上限、生命值、攻防护盾金币和经验值 + var statusList = ['hpmax', 'hp', 'mana', 'atk', 'def', 'mdef', 'money', 'exp']; + statusList.forEach(function (item) { + // 向下取整 + core.status.hero[item] = Math.floor(core.status.hero[item]); + // 大数据格式化 + core.setStatusBarInnerHTML(item, core.getRealStatus(item)); + }); + + // 设置魔力值; status:manamax 只有在非负时才生效。 + if (core.status.hero.manamax != null && core.getRealStatus('manamax') >= 0) { + core.status.hero.mana = Math.min(core.status.hero.mana, core.getRealStatus('manamax')); + core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.getRealStatus('manamax')); + } else { + core.setStatusBarInnerHTML("mana", core.status.hero.mana); + } + // 设置技能栏 + // 可以用flag:skill表示当前开启的技能类型,flag:skillName显示技能名;详见文档-个性化-技能塔的支持 + core.setStatusBarInnerHTML('skill', core.getFlag('skillName', '无')); + + // 可以在这里添加自己额外的状态栏信息,比如想攻击显示 +0.5 可以这么写: + // if (core.hasFlag('halfAtk')) core.setStatusBarInnerHTML('atk', core.statusBar.atk.innerText + "+0.5"); + + // 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值 + + // 进阶 + if (core.flags.statusBarItems.indexOf('enableLevelUp') >= 0) { + core.setStatusBarInnerHTML('up', core.formatBigNumber(core.getNextLvUpNeed()) || ""); + } else core.setStatusBarInnerHTML('up', ""); + + // 钥匙 + var keys = ['yellowKey', 'blueKey', 'redKey', 'greenKey']; + keys.forEach(function (key) { + core.setStatusBarInnerHTML(key, core.setTwoDigits(core.itemCount(key))); + }); + // 毒衰咒 + core.setStatusBarInnerHTML('poison', core.hasFlag('poison') ? "毒" : ""); + core.setStatusBarInnerHTML('weak', core.hasFlag('weak') ? "衰" : ""); + core.setStatusBarInnerHTML('curse', core.hasFlag('curse') ? "咒" : ""); + // 破炸飞 + core.setStatusBarInnerHTML('pickaxe', "破" + core.itemCount('pickaxe')); + core.setStatusBarInnerHTML('bomb', "炸" + core.itemCount('bomb')); + core.setStatusBarInnerHTML('fly', "飞" + core.itemCount('centerFly')); + + // 难度 + if (core.statusBar.hard.innerText != core.status.hard) { + core.statusBar.hard.innerText = core.status.hard; + } + var hardColor = core.getFlag('__hardColor__', 'red'); + if (core.statusBar.hard.getAttribute('_style') != hardColor) { + core.statusBar.hard.style.color = hardColor; + core.statusBar.hard.setAttribute('_style', hardColor); + } + // 自定义状态栏绘制 + core.drawStatusBar(); + + // 更新阻激夹域的伤害值 + core.updateCheckBlock(); + // 更新全地图显伤 + core.updateDamage(); + }, + "updateCheckBlock": function (floorId) { + // 领域、夹击、阻击等的伤害值计算 + floorId = floorId || core.status.floorId; + if (!floorId || !core.status.maps) return; + + var width = core.floors[floorId].width, + height = core.floors[floorId].height; + var blocks = core.getMapBlocksObj(floorId); + + var damage = {}, // 每个点的伤害值 + type = {}, // 每个点的伤害类型 + repulse = {}, // 每个点的阻击怪信息 + ambush = {}; // 每个点的捕捉信息 + var betweenAttackLocs = {}; // 所有可能的夹击点 + var needCache = false; + var canGoDeadZone = core.flags.canGoDeadZone; + core.flags.canGoDeadZone = true; + + // 计算血网和领域、阻击、激光的伤害,计算捕捉信息 + for (var loc in blocks) { + var block = blocks[loc], + x = block.x, + y = block.y, + id = block.event.id, + enemy = core.material.enemys[id]; + if (block.disable) continue; + + type[loc] = type[loc] || {}; + + // 血网 + // 如需调用当前楼层的ratio可使用 core.status.maps[floorId].ratio + if (id == 'lavaNet' && !core.hasItem('amulet')) { + damage[loc] = (damage[loc] || 0) + core.values.lavaDamage; + type[loc][(block.event.name || "血网") + "伤害"] = true; + } + + // 领域 + // 如果要防止领域伤害,可以直接简单的将 flag:no_zone 设为true + if (enemy && core.hasSpecial(enemy.special, 15) && !core.hasFlag('no_zone')) { + // 领域范围,默认为1 + var range = enemy.range || 1; + // 是否是九宫格领域 + var zoneSquare = false; + if (enemy.zoneSquare != null) zoneSquare = enemy.zoneSquare; + // 在范围内进行搜索,增加领域伤害值 + for (var dx = -range; dx <= range; dx++) { + for (var dy = -range; dy <= range; dy++) { + if (dx == 0 && dy == 0) continue; + var nx = x + dx, + ny = y + dy, + currloc = nx + "," + ny; + if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; + // 如果是十字领域,则还需要满足 |dx|+|dy|<=range + if (!zoneSquare && Math.abs(dx) + Math.abs(dy) > range) continue; + damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); + type[currloc] = type[currloc] || {}; + type[currloc]["领域伤害"] = true; + } + } + } + + // 阻击 + // 如果要防止阻击伤害,可以直接简单的将 flag:no_repulse 设为true + if (enemy && core.hasSpecial(enemy.special, 18) && !core.hasFlag('no_repulse')) { + var scan = enemy.zoneSquare ? core.utils.scan2 : core.utils.scan; + for (var dir in scan) { + var nx = x + scan[dir].x, + ny = y + scan[dir].y, + currloc = nx + "," + ny; + if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; + damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); + type[currloc] = type[currloc] || {}; + type[currloc]["阻击伤害"] = true; + + var rdir = core.turnDirection(":back", dir); + // 检查下一个点是否存在事件(从而判定是否移动) + var rnx = x + scan[rdir].x, + rny = y + scan[rdir].y; + if (rnx < 0 || rnx >= width || rny < 0 || rny >= height) continue; + // 如需禁止阻击被推到已隐藏的事件处(如重生怪处),可将这一句的false改为true + if (core.getBlock(rnx, rny, floorId, false) != null) continue; + if (core.utils.scan[rdir] && !core.canMoveHero(x, y, rdir, floorId)) continue; + repulse[currloc] = (repulse[currloc] || []).concat([ + [x, y, id, rdir] + ]); + } + } + + // 激光 + // 如果要防止激光伤害,可以直接简单的将 flag:no_laser 设为true + if (enemy && core.hasSpecial(enemy.special, 24) && !core.hasFlag("no_laser")) { + for (var nx = 0; nx < width; nx++) { + var currloc = nx + "," + y; + if (nx != x) { + damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); + type[currloc] = type[currloc] || {}; + type[currloc]["激光伤害"] = true; + } + } + for (var ny = 0; ny < height; ny++) { + var currloc = x + "," + ny; + if (ny != y) { + damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); + type[currloc] = type[currloc] || {}; + type[currloc]["激光伤害"] = true; + } + } + } + + // 捕捉 + // 如果要防止捕捉效果,可以直接简单的将 flag:no_ambush 设为true + if (enemy && core.enemys.hasSpecial(enemy.special, 27) && !core.hasFlag("no_ambush")) { + var scan = enemy.zoneSquare ? core.utils.scan2 : core.utils.scan; + // 给周围格子加上【捕捉】记号 + for (var dir in scan) { + var nx = x + scan[dir].x, + ny = y + scan[dir].y, + currloc = nx + "," + ny; + if (nx < 0 || nx >= width || ny < 0 || ny >= height || (core.utils.scan[dir] && !core.canMoveHero(x, y, dir, floorId))) continue; + ambush[currloc] = (ambush[currloc] || []).concat([ + [x, y, id, dir] + ]); + } + } + + // 夹击;在这里提前计算所有可能的夹击点,具体计算逻辑在下面 + // 如果要防止夹击伤害,可以简单的将 flag:no_betweenAttack 设为true + if (enemy && core.enemys.hasSpecial(enemy.special, 16) && !core.hasFlag('no_betweenAttack')) { + for (var dir in core.utils.scan) { + var nx = x + core.utils.scan[dir].x, + ny = y + core.utils.scan[dir].y, + currloc = nx + "," + ny; + if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; + betweenAttackLocs[currloc] = true; + } + } + + // 检查地图范围类技能 + var specialFlag = core.getSpecialFlag(enemy); + if (specialFlag & 1) needCache = true; + if (core.status.event.id == 'viewMaps') needCache = true; + if ((core.status.event.id == 'book' || core.status.event.id == 'bool-detail') && core.status.event.ui) needCache = true; + } + + // 对每个可能的夹击点计算夹击伤害 + for (var loc in betweenAttackLocs) { + var xy = loc.split(","), + x = parseInt(xy[0]), + y = parseInt(xy[1]); + // 夹击怪物的ID + var enemyId1 = null, + enemyId2 = null; + // 检查左右夹击 + var leftBlock = blocks[(x - 1) + "," + y], + rightBlock = blocks[(x + 1) + "," + y]; + var leftId = core.getFaceDownId(leftBlock), + rightId = core.getFaceDownId(rightBlock); + if (leftBlock && !leftBlock.disable && rightBlock && !rightBlock.disable && leftId == rightId) { + if (core.hasSpecial(leftId, 16)) + enemyId1 = leftId; + } + // 检查上下夹击 + var topBlock = blocks[x + "," + (y - 1)], + bottomBlock = blocks[x + "," + (y + 1)]; + var topId = core.getFaceDownId(topBlock), + bottomId = core.getFaceDownId(bottomBlock); + if (topBlock && !topBlock.disable && bottomBlock && !bottomBlock.disable && topId == bottomId) { + if (core.hasSpecial(topId, 16)) + enemyId2 = topId; + } + + if (enemyId1 != null || enemyId2 != null) { + var leftHp = core.status.hero.hp - (damage[loc] || 0); + if (leftHp > 1) { + // 夹击伤害值 + var value = Math.floor(leftHp / 2); + // 是否不超过怪物伤害值 + if (core.flags.betweenAttackMax) { + var enemyDamage1 = core.getDamage(enemyId1, x, y, floorId); + if (enemyDamage1 != null && enemyDamage1 < value) + value = enemyDamage1; + var enemyDamage2 = core.getDamage(enemyId2, x, y, floorId); + if (enemyDamage2 != null && enemyDamage2 < value) + value = enemyDamage2; + } + if (value > 0) { + damage[loc] = (damage[loc] || 0) + value; + type[loc] = type[loc] || {}; + type[loc]["夹击伤害"] = true; + } + } + } + } + + // 取消注释下面这一段可以让护盾抵御阻激夹域伤害 + /* + for (var loc in damage) { + damage[loc] = Math.max(0, damage[loc] - core.getRealStatus('mdef')); + } + */ + + core.flags.canGoDeadZone = canGoDeadZone; + core.status.checkBlock = { + damage: damage, + type: type, + repulse: repulse, + ambush: ambush, + needCache: needCache, + cache: {} // clear cache + }; + }, + "moveOneStep": function (callback) { + // 勇士每走一步后执行的操作。callback为行走完毕后的回调 + // 这个函数执行在“刚走完”的时候,即还没有检查该点的事件和领域伤害等。 + // 请注意:瞬间移动不会执行该函数。如果要控制能否瞬间移动有三种方法: + // 1. 将全塔属性中的cannotMoveDirectly这个开关勾上,即可在全塔中全程禁止使用瞬移。 + // 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。 + // 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。 + + // 增加步数 + core.status.hero.steps++; + // 更新跟随者状态,并绘制 + core.updateFollowers(); + core.drawHero(); + // 检查中毒状态的扣血和死亡 + if (core.hasFlag('poison')) { + core.status.hero.statistics.poisonDamage += core.values.poisonDamage; + core.status.hero.hp -= core.values.poisonDamage; + if (core.status.hero.hp <= 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + return; + } else { + core.updateStatusBar(); + } + } + + // 从v2.7开始,每一步行走不会再刷新状态栏。 + // 如果有特殊要求(如每走一步都加buff之类),可手动取消注释下面这一句: + // core.updateStatusBar(true); + + // 检查自动事件 + core.checkAutoEvents(); + + // ------ 检查目标点事件 ------ // + // 无事件的道具(如血瓶)需要优先于阻激夹域判定 + var nowx = core.getHeroLoc('x'), + nowy = core.getHeroLoc('y'); + var block = core.getBlock(nowx, nowy); + var hasTrigger = false; + if (block != null && block.event.trigger == 'getItem' && + !core.floors[core.status.floorId].afterGetItem[nowx + "," + nowy]) { + hasTrigger = true; + core.trigger(nowx, nowy, callback); + } + // 执行目标点的阻激夹域事件 + core.checkBlock(); + + // 执行目标点的script和事件 + if (!hasTrigger) + core.trigger(nowx, nowy, callback); + + // 检查该点是否是滑冰 + if (core.onSki()) { + // 延迟到事件最后执行,因为这之前可能有阻激夹域动画 + core.insertAction({ "type": "moveAction" }, null, null, null, true); + } + + // ------ 检查目标点事件 END ------ // + + // 如需强行终止行走可以在这里条件判定: + // core.stopAutomaticRoute(); + }, + "moveDirectly": function (x, y, ignoreSteps) { + // 瞬间移动;x,y为要瞬间移动的点;ignoreSteps为减少的步数,可能之前已经被计算过 + // 返回true代表成功瞬移,false代表没有成功瞬移 + + // 判定能否瞬移到该点 + if (ignoreSteps == null) ignoreSteps = core.canMoveDirectly(x, y); + if (ignoreSteps >= 0) { + // 中毒也允许瞬移 + if (core.hasFlag('poison')) { + var damage = ignoreSteps * core.values.poisonDamage; + if (damage >= core.status.hero.hp) return false; + core.status.hero.statistics.poisonDamage += damage; + core.status.hero.hp -= damage; + } + + core.clearMap('hero'); + // 获得勇士最后的朝向 + var lastDirection = core.status.route[core.status.route.length - 1]; + if (['left', 'right', 'up', 'down'].indexOf(lastDirection) >= 0) + core.setHeroLoc('direction', lastDirection); + // 设置坐标,并绘制 + core.control._moveDirectyFollowers(x, y); + core.status.hero.loc.x = x; + core.status.hero.loc.y = y; + core.drawHero(); + // 记录录像 + core.status.route.push("move:" + x + ":" + y); + // 统计信息 + core.status.hero.statistics.moveDirectly++; + core.status.hero.statistics.ignoreSteps += ignoreSteps; + if (core.hasFlag('poison')) { + core.updateStatusBar(); + } + core.checkRouteFolding(); + return true; + } + return false; + }, + "parallelDo": function (timestamp) { + // 并行事件处理,可以在这里写任何需要并行处理的脚本或事件 + // 该函数将被系统反复执行,每次执行间隔视浏览器或设备性能而定,一般约为16.6ms一次 + // 参数timestamp为“从游戏资源加载完毕到当前函数执行时”的时间差,以毫秒为单位 + + // 检查当前是否处于游戏开始状态 + if (!core.isPlaying()) return; + + // 执行当前楼层的并行事件处理 + if (core.status.floorId) { + try { + eval(core.floors[core.status.floorId].parallelDo); + } catch (e) { + main.log(e); + } + } + } + }, + "ui": { + "getToolboxItems": function (cls) { + // 获得道具栏中当前某类型道具的显示项和显示顺序 + // cls为道具类型,只可能是 tools, constants 和 equips + // 返回一个数组,代表当前某类型道具的显示内容和顺序 + // 默认按id升序排列,您可以取消下面的注释改为按名称排列 + + return Object.keys(core.status.hero.items[cls] || {}) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }) + .sort( /*function (id1, id2) { return core.material.items[id1].name <= core.material.items[id2].name ? -1 : 1 }*/); + }, + "drawStatusBar": function () { + // 自定义绘制状态栏,需要开启状态栏canvas化 + + // 如果是非状态栏canvas化,直接返回 + if (!core.flags.statusCanvas) return; + var ctx = core.dom.statusCanvasCtx; + // 清空状态栏 + core.clearMap(ctx); + // 如果是隐藏状态栏模式,直接返回 + if (!core.domStyle.showStatusBar) return; + + // 作为样板,只绘制楼层、生命、攻击、防御、护盾、金币、钥匙这七个内容 + // 需要其他的请自行进行修改;横竖屏都需要进行适配绘制。 + // (可以使用Chrome浏览器开控制台来模拟手机上的竖屏模式的显示效果,具体方式自行百度) + // 横屏模式下的画布大小是 129*416 + // 竖屏模式下的画布大小是 416*(32*rows+9) 其中rows为状态栏行数,即全塔属性中statusCanvasRowsOnMobile值 + // 可以使用 core.domStyle.isVertical 来判定当前是否是竖屏模式 + + core.setFillStyle(ctx, core.status.globalAttribute.statusBarColor || core.initStatus.globalAttribute.statusBarColor); + + // 绘制一段文字,带斜体判定 + var _fillBoldTextWithFontCheck = function (text, x, y, style) { + // 斜体判定:如果不是纯数字和字母,斜体会非常难看,需要取消 + if (!/^[-a-zA-Z0-9`~!@#$%^&*()_=+\[{\]}\\|;:'",<.>\/?]*$/.test(text)) + core.setFont(ctx, 'bold 18px Verdana'); + else core.setFont(ctx, 'italic bold 18px Verdana'); + core.fillBoldText(ctx, text, x, y, style); + } + + // 横竖屏需要分别绘制... + if (!core.domStyle.isVertical) { + // 横屏模式 + + // 绘制楼层 + core.drawImage(ctx, core.statusBar.icons.floor, 6, 9, 25, 25); + _fillBoldTextWithFontCheck((core.status.thisMap || {}).name || "", 42, 29); + + // 绘制生命 + core.drawImage(ctx, core.statusBar.icons.hp, 6, 43, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('hp')), 42, 63); + + // 绘制攻击 + core.drawImage(ctx, core.statusBar.icons.atk, 6, 77, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('atk')), 42, 97); + + // 绘制防御 + core.drawImage(ctx, core.statusBar.icons.def, 6, 111, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('def')), 42, 131); + + // 绘制护盾 + core.drawImage(ctx, core.statusBar.icons.mdef, 6, 145, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('mdef')), 42, 165); + + // 绘制金币 + core.drawImage(ctx, core.statusBar.icons.money, 6, 179, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.money), 42, 199); + + // 绘制经验 + core.drawImage(ctx, core.statusBar.icons.exp, 6, 213, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.exp), 42, 233); + + // 绘制三色钥匙 + _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('yellowKey')), 11, 267, '#FFCCAA'); + _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('blueKey')), 46, 267, '#AAAADD'); + _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('redKey')), 81, 267, '#FF8888'); + + } else { + // 竖屏模式 + + // 绘制楼层 + core.drawImage(ctx, core.statusBar.icons.floor, 6, 6, 25, 25); + _fillBoldTextWithFontCheck((core.status.thisMap || {}).name || "", 42, 26); + + // 绘制生命 + core.drawImage(ctx, core.statusBar.icons.hp, 137, 6, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('hp')), 173, 26); + + // 绘制攻击 + core.drawImage(ctx, core.statusBar.icons.atk, 268, 6, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('atk')), 304, 26); + + // 绘制防御 + core.drawImage(ctx, core.statusBar.icons.def, 6, 38, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('def')), 42, 58); + + // 绘制护盾 + core.drawImage(ctx, core.statusBar.icons.mdef, 137, 38, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('mdef')), 173, 58); + + // 绘制金币 + core.drawImage(ctx, core.statusBar.icons.money, 268, 38, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.money), 304, 58); + + // 绘制经验 + core.drawImage(ctx, core.statusBar.icons.exp, 6, 70, 25, 25); + _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.exp), 42, 90); + + // 绘制三色钥匙 + _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('yellowKey')), 142, 90, '#FFCCAA'); + _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('blueKey')), 177, 90, '#AAAADD'); + _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('redKey')), 212, 90, '#FF8888'); + } + }, + "drawStatistics": function () { + // 浏览地图时参与的统计项目 + + return [ + 'yellowDoor', 'blueDoor', 'redDoor', 'greenDoor', 'steelDoor', + 'yellowKey', 'blueKey', 'redKey', 'greenKey', 'steelKey', + 'redGem', 'blueGem', 'greenGem', 'yellowGem', + 'redPotion', 'bluePotion', 'greenPotion', 'yellowPotion', 'superPotion', + 'pickaxe', 'bomb', 'centerFly', 'icePickaxe', 'freezeBadge', + 'earthquake', 'upFly', 'downFly', 'jumpShoes', 'lifeWand', + 'poisonWine', 'weakWine', 'curseWine', 'superWine', + 'sword1', 'sword2', 'sword3', 'sword4', 'sword5', + 'shield1', 'shield2', 'shield3', 'shield4', 'shield5', + // 在这里可以增加新的ID来进行统计个数,只能增加道具ID + ]; + }, + "drawAbout": function () { + // 绘制“关于”界面 + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'about'; + + var left = 48, + top = 36, + right = core.__PIXELS__ - 2 * left, + bottom = core.__PIXELS__ - 2 * top; + + core.setAlpha('ui', 0.85); + core.fillRect('ui', left, top, right, bottom, '#000000'); + core.setAlpha('ui', 1); + core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2); + + var text_start = left + 24; + + // 名称 + core.setTextAlign('ui', 'left'); + var globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute; + core.fillText('ui', "HTML5 魔塔样板", text_start, top + 35, globalAttribute.selectColor, "bold 22px " + globalAttribute.font); + core.fillText('ui', "版本: " + main.__VERSION__, text_start, top + 80, "#FFFFFF", "bold 17px " + globalAttribute.font); + core.fillText('ui', "作者: 艾之葵", text_start, top + 112); + core.fillText('ui', 'HTML5魔塔交流群:539113091', text_start, top + 112 + 32); + // TODO: 写自己的“关于”页面,每次增加32像素即可 + core.playSound('打开界面'); } } -} - }, - "ui": { - "getToolboxItems": function (cls) { - // 获得道具栏中当前某类型道具的显示项和显示顺序 - // cls为道具类型,只可能是 tools, constants 和 equips - // 返回一个数组,代表当前某类型道具的显示内容和顺序 - // 默认按id升序排列,您可以取消下面的注释改为按名称排列 - - return Object.keys(core.status.hero.items[cls] || {}) - .filter(function (id) { return !core.material.items[id].hideInToolbox; }) - .sort( /*function (id1, id2) { return core.material.items[id1].name <= core.material.items[id2].name ? -1 : 1 }*/ ); -}, - "drawStatusBar": function () { - // 自定义绘制状态栏,需要开启状态栏canvas化 - - // 如果是非状态栏canvas化,直接返回 - if (!core.flags.statusCanvas) return; - var ctx = core.dom.statusCanvasCtx; - // 清空状态栏 - core.clearMap(ctx); - // 如果是隐藏状态栏模式,直接返回 - if (!core.domStyle.showStatusBar) return; - - // 作为样板,只绘制楼层、生命、攻击、防御、护盾、金币、钥匙这七个内容 - // 需要其他的请自行进行修改;横竖屏都需要进行适配绘制。 - // (可以使用Chrome浏览器开控制台来模拟手机上的竖屏模式的显示效果,具体方式自行百度) - // 横屏模式下的画布大小是 129*416 - // 竖屏模式下的画布大小是 416*(32*rows+9) 其中rows为状态栏行数,即全塔属性中statusCanvasRowsOnMobile值 - // 可以使用 core.domStyle.isVertical 来判定当前是否是竖屏模式 - - core.setFillStyle(ctx, core.status.globalAttribute.statusBarColor || core.initStatus.globalAttribute.statusBarColor); - - // 绘制一段文字,带斜体判定 - var _fillBoldTextWithFontCheck = function (text, x, y, style) { - // 斜体判定:如果不是纯数字和字母,斜体会非常难看,需要取消 - if (!/^[-a-zA-Z0-9`~!@#$%^&*()_=+\[{\]}\\|;:'",<.>\/?]*$/.test(text)) - core.setFont(ctx, 'bold 18px Verdana'); - else core.setFont(ctx, 'italic bold 18px Verdana'); - core.fillBoldText(ctx, text, x, y, style); - } - - // 横竖屏需要分别绘制... - if (!core.domStyle.isVertical) { - // 横屏模式 - - // 绘制楼层 - core.drawImage(ctx, core.statusBar.icons.floor, 6, 9, 25, 25); - _fillBoldTextWithFontCheck((core.status.thisMap || {}).name || "", 42, 29); - - // 绘制生命 - core.drawImage(ctx, core.statusBar.icons.hp, 6, 43, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('hp')), 42, 63); - - // 绘制攻击 - core.drawImage(ctx, core.statusBar.icons.atk, 6, 77, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('atk')), 42, 97); - - // 绘制防御 - core.drawImage(ctx, core.statusBar.icons.def, 6, 111, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('def')), 42, 131); - - // 绘制护盾 - core.drawImage(ctx, core.statusBar.icons.mdef, 6, 145, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('mdef')), 42, 165); - - // 绘制金币 - core.drawImage(ctx, core.statusBar.icons.money, 6, 179, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.money), 42, 199); - - // 绘制经验 - core.drawImage(ctx, core.statusBar.icons.exp, 6, 213, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.exp), 42, 233); - - // 绘制三色钥匙 - _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('yellowKey')), 11, 267, '#FFCCAA'); - _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('blueKey')), 46, 267, '#AAAADD'); - _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('redKey')), 81, 267, '#FF8888'); - - } else { - // 竖屏模式 - - // 绘制楼层 - core.drawImage(ctx, core.statusBar.icons.floor, 6, 6, 25, 25); - _fillBoldTextWithFontCheck((core.status.thisMap || {}).name || "", 42, 26); - - // 绘制生命 - core.drawImage(ctx, core.statusBar.icons.hp, 137, 6, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('hp')), 173, 26); - - // 绘制攻击 - core.drawImage(ctx, core.statusBar.icons.atk, 268, 6, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('atk')), 304, 26); - - // 绘制防御 - core.drawImage(ctx, core.statusBar.icons.def, 6, 38, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('def')), 42, 58); - - // 绘制护盾 - core.drawImage(ctx, core.statusBar.icons.mdef, 137, 38, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.getRealStatus('mdef')), 173, 58); - - // 绘制金币 - core.drawImage(ctx, core.statusBar.icons.money, 268, 38, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.money), 304, 58); - - // 绘制经验 - core.drawImage(ctx, core.statusBar.icons.exp, 6, 70, 25, 25); - _fillBoldTextWithFontCheck(core.formatBigNumber(core.status.hero.exp), 42, 90); - - // 绘制三色钥匙 - _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('yellowKey')), 142, 90, '#FFCCAA'); - _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('blueKey')), 177, 90, '#AAAADD'); - _fillBoldTextWithFontCheck(core.setTwoDigits(core.itemCount('redKey')), 212, 90, '#FF8888'); - } -}, - "drawStatistics": function () { - // 浏览地图时参与的统计项目 - - return [ - 'yellowDoor', 'blueDoor', 'redDoor', 'greenDoor', 'steelDoor', - 'yellowKey', 'blueKey', 'redKey', 'greenKey', 'steelKey', - 'redGem', 'blueGem', 'greenGem', 'yellowGem', - 'redPotion', 'bluePotion', 'greenPotion', 'yellowPotion', 'superPotion', - 'pickaxe', 'bomb', 'centerFly', 'icePickaxe', 'freezeBadge', - 'earthquake', 'upFly', 'downFly', 'jumpShoes', 'lifeWand', - 'poisonWine', 'weakWine', 'curseWine', 'superWine', - 'sword1', 'sword2', 'sword3', 'sword4', 'sword5', - 'shield1', 'shield2', 'shield3', 'shield4', 'shield5', - // 在这里可以增加新的ID来进行统计个数,只能增加道具ID - ]; -}, - "drawAbout": function () { - // 绘制“关于”界面 - core.ui.closePanel(); - core.lockControl(); - core.status.event.id = 'about'; - - var left = 48, - top = 36, - right = core.__PIXELS__ - 2 * left, - bottom = core.__PIXELS__ - 2 * top; - - core.setAlpha('ui', 0.85); - core.fillRect('ui', left, top, right, bottom, '#000000'); - core.setAlpha('ui', 1); - core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2); - - var text_start = left + 24; - - // 名称 - core.setTextAlign('ui', 'left'); - var globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute; - core.fillText('ui', "HTML5 魔塔样板", text_start, top + 35, globalAttribute.selectColor, "bold 22px " + globalAttribute.font); - core.fillText('ui', "版本: " + main.__VERSION__, text_start, top + 80, "#FFFFFF", "bold 17px " + globalAttribute.font); - core.fillText('ui', "作者: 艾之葵", text_start, top + 112); - core.fillText('ui', 'HTML5魔塔交流群:539113091', text_start, top + 112 + 32); - // TODO: 写自己的“关于”页面,每次增加32像素即可 - core.playSound('打开界面'); -} - } } \ No newline at end of file diff --git a/runtime.d.ts b/runtime.d.ts index f1703043..d8772cd8 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -8,14 +8,16 @@ type move = 'forward' | direction type loc = { direction: direction, x: number, y: number } type rgbarray = [number, number, number, number] -type Block = { - x: number, - y: number, - id: number, - event: { - cls: string, - id: string, - [key: string]: any +type Events = MotaAction[] | string + +type Block = { + x: number, + y: number, + id: number, + event: { + cls: string, + id: string, + [key: string]: any } } @@ -45,7 +47,53 @@ type Floor = { } type ResolvedMap = { - + floorId: string + afterBattle: { [x: string]: Events } + afterOpenDoor: { [x: string]: Events } + afterGetItem: { [x: string]: Events } + autoEvent: Event + beforeBattle: { [x: string]: Events } + canFlyFrom: boolean + canFltTo: boolean + canUseQuickShop: boolean + cannotMove: Object + cannotMoveIn: Object + cannotViewMap: boolean + changeFloor: { + [x: string]: { + floorId: ':before' | ':after' | ':now' | string + loc?: [number, number] + stair?: 'upFloor' | 'downFloor' | ':symmetry' | ':symmetry_x' | ':symmetry_y' | 'flyPoint' + direction?: 'left' | 'right' | 'up' | 'down' | ':left' | ':right' | ':back' | ':hero' | ':backhero' + time?: number + ignoreChangeFloor?: boolean + } + } + defaultGround: string + bgm: string | Array + bgmap: number[][] + /** 事件层 */ + map: number[][] + fgmap: number[][] + width: number + height: number + images: Array<{ + canvas: 'bg' | 'auto' | 'fg' + name: string + x: number + y: number + reverse?: ':x' | ':y' | ':o' + disable?: boolean + sx?: number + sy?: number + w?: number + h?: number + frame?: numer + }> + name: string + ratio: number + title: string + weather: [string, number] } type Enemy = { @@ -68,12 +116,12 @@ type Item = { } type Save = { - + } -type MotaAction = { - type: string, - [key: string]: any +type MotaAction = { + type: string, + [key: string]: any } | string type SystemFlags = { @@ -87,7 +135,7 @@ type SystemFlags = { } type event = { type: string, [key: string]: any } - + type step = 'up' | 'down' | 'left' | 'right' | 'forward' | 'backward' type HeroStatus = { @@ -150,12 +198,46 @@ type gameStatus = { fgmaps: { [key: string]: number[][] } mapBlockObjs: { [key: string]: any } /** 显伤伤害 */ - checkBlock: {} - damage: {} + checkBlock: { + ambush: { [x: string]: [number, number, string, direction] } + repulse: { [x: string]: [number, number, string, direction] } + damage: { [x: string]: number } + needCache: boolean + type: { [x: string]: { [x: string]: boolean } } + cache: { + [s: string]: { + hp_buff: number + atk_buff: number + def_buff: number + guards: [number, number, string] + } + } + } + damage: { + posX: number + posY: number + data: Array<{ + [x: string]: { + text: string + px: number + py: number + color: string | Array + } + }> + extraData: Array<{ + [x: string]: { + text: string + px: number + py: number + color: string | Array + alpha: number + } + }> + } lockControl: boolean - /** 勇士移动状态 */ + /** 勇士移动状态 */ heroMoving: number heroStop: boolean @@ -182,13 +264,13 @@ type gameStatus = { ctrlDown: boolean // 路线&回放 - route: [], + route: string[], replay: { replaying: boolean pausing: boolean /** 正在某段动画中 */animate: boolean - toReplay: [] - totalList: [] + toReplay: string[] + totalList: string[] speed: number steps: number save: [] @@ -197,13 +279,13 @@ type gameStatus = { // event事件 shops: {} event: { - id: null - data: null - selection: null - ui: null - interval: null + id: string + data: any + selection: any + ui: any + interval: number } - autoEvents: [] + autoEvents: Events textAttribute: { position: string offset: number @@ -253,28 +335,6 @@ declare class control { */ updateStatusBar(doNotCheckAutoEvents?: boolean): void - /** - * 设置某个自定义变量或flag - * @example core.setFlag('xyz', 2) // 设置变量xyz为2 - * @param name 变量名 - * @param value 要设置的值 - */ - setFlag(name: string, value: any): void - - /** - * 获取某个自定义变量或flag - * @example core.getFlag('point', 2) // 获得变量point的值;如果该变量从未定义过则返回2 - * @param name 变量名 - * @param defaultValue 该变量不存在时返回的值。 - * @returns 变量的值 - */ - getFlag(name: string, defaultValue: any): any - - /** - * 返回是否存在某个变量且不为0。等价于 core.getFlag('xyz', 0)!=0 - */ - hasFlag(name: string): boolean - /** 删除某个flag/变量 */ removeFlag(name: string): void @@ -304,7 +364,7 @@ declare class control { /** 回放下一个操作 */ replay(): void - + /** * 进入标题画面 * @example core.showStartAnimate(); // 重启游戏但不重置bgm @@ -312,14 +372,14 @@ declare class control { * @param callback 可选,完全亮屏后的回调函数 */ showStartAnimate(noAnimate?: boolean, callback?: () => void): void - + /** * 淡出标题画面 * @example core.hideStartAnimate(core.startGame); // 淡出标题画面并开始新游戏,跳过难度选择 * @param callback 标题画面完全淡出后的回调函数 */ hideStartAnimate(callback?: () => void): void - + /** * 半自动寻路,用于鼠标或手指拖动 * @example core.setAutomaticRoute(0, 0, [{direction: "right", x: 4, y: 9}, {direction: "right", x: 5, y: 9}, {direction: "right", x: 6, y: 9}, {direction: "up", x: 6, y: 8}]); @@ -328,21 +388,21 @@ declare class control { * @param stepPostfix 拖动轨迹的数组表示,每项为一步的方向和目标点。 */ setAutomaticRoute(destX: number, destY: number, stepPostfix: Array<{ direction: direction, x: number, y: number }>): void - + /** * 连续行走 * @example core.setAutoHeroMove([{direction: "up", step: 1}, {direction: "left", step: 3}, {direction: "right", step: 3}, {direction: "up", step: 9}]); // 上左左左右右右上9 * @param steps 压缩的步伐数组,每项表示朝某方向走多少步 */ setAutoHeroMove(steps: Array<{ direction: direction, step: number }>): void - + /** * 尝试前进一步,如果面前不可被踏入就会直接触发该点事件 * @example core.moveAction(core.doAction); // 尝试前进一步,然后继续事件处理。常用于在事件流中让主角像自由行动时一样前进一步,可以照常触发moveOneStep(跑毒和计步)和面前的事件(包括但不限于阻激夹域捕) * @param callback 走一步后的回调函数,可选 */ moveAction(callback?: () => void): void - + /** * 连续前进,不撞南墙不回头 * @example core.moveHero(); // 连续前进 @@ -350,21 +410,21 @@ declare class control { * @param callback 可选,如果设置了就只走一步 */ moveHero(direction?: direction, callback?: () => void): void - + /** * 等待主角停下 * @example core.waitHeroToStop(core.vibrate); // 等待主角停下,然后视野左右抖动1秒 * @param callback 主角停止后的回调函数 */ waitHeroToStop(callback?: () => void): void - + /** * 主角转向并计入录像,不会导致跟随者聚集,会导致视野重置到以主角为中心 * @example core.turnHero(); // 主角顺时针旋转90°,即单击主角或按下Z键的效果 * @param direction 主角的新朝向,可为 up, down, left, right, :left, :right, :back 七种之一 */ turnHero(direction?: direction): void - + /** * 尝试瞬移,如果该点有图块/事件/阻激夹域捕则会瞬移到它旁边再走一步(不可踏入的话当然还是触发该点事件),这一步的方向优先和瞬移前主角的朝向一致 * @example core.tryMoveDirectly(6, 0); // 尝试瞬移到地图顶部的正中央,以样板0层为例,实际效果是瞬移到了上楼梯下面一格然后向上走一步并触发上楼事件 @@ -372,7 +432,7 @@ declare class control { * @param destY 目标点的纵坐标 */ tryMoveDirectly(destX: number, destY: number): void - + /** * 绘制主角和跟随者并重置视野到以主角为中心 * @example core.drawHero(); // 原地绘制主角的静止帧 @@ -381,21 +441,21 @@ declare class control { * @param frame 绘制第几帧 */ drawHero(status?: 'stop' | 'leftFoot' | 'rightFoot', offset?: number, frame?: number): void - + /** * 获取主角面前第n格的横坐标 * @example core.closeDoor(core.nextX(), core.nextY(), 'yellowDoor', core.turnHero); // 在主角面前关上一扇黄门,然后主角顺时针旋转90° * @param n 目标格与主角的距离,面前为正数,背后为负数,脚下为0,不填视为1 */ nextX(n?: number): number - + /** * 获取主角面前第n格的纵坐标 * @example core.jumpHero(core.nextX(2), core.nextY(2)); // 主角向前跃过一格,即跳跃靴道具的使用效果 * @param n 目标格与主角的距离,面前为正数,背后为负数,脚下为0,不填视为1 */ nextY(n?: number): number - + /** * 判定主角是否身处某个点的锯齿领域(取曼哈顿距离) * @example core.nearHero(6, 6, 6); // 判定主角是否身处点(6,6)的半径为6的锯齿领域 @@ -404,15 +464,15 @@ declare class control { * @param n 领域的半径,不填视为1 */ nearHero(x: number, y: number, n?: number): boolean - + /** - * 重算并绘制地图显伤 + * 请不要直接使用该函数,请使用core.updateStatusBar()代替!重算并绘制地图显伤 * @example core.updateDamage(); // 更新当前地图的显伤,绘制在显伤层(废话) * @param floorId 地图id,不填视为当前地图。预览地图时填写 * @param ctx 绘制到的画布,如果填写了就会画在该画布而不是显伤层 */ updateDamage(floorId?: string, ctx?: CanvasRenderingContext2D): void - + /** 仅重绘地图显伤 */ drawDamage(ctx?: CanvasRenderingContext2D): void @@ -423,7 +483,7 @@ declare class control { * @param value 属性的新值 */ setStatus(name: K, value: HeroStatus[K]): void - + /** * 增减主角的某个属性,等价于core.setStatus(name, core.getStatus(name) + value) * @example core.addStatus('name', '酱'); // 在主角的名字后加一个“酱”字 @@ -431,7 +491,7 @@ declare class control { * @param value 属性的增量,请注意旧量和增量中只要有一个是字符串就会把两者连起来成为一个更长的字符串 */ addStatus(name: K, value: HeroStatus[K]): void - + /** * 读取主角的某个属性,不包括百分比修正 * @example core.getStatus('loc'); // 读取主角的坐标和朝向 @@ -439,17 +499,17 @@ declare class control { * @returns 属性值 */ getStatus(name: K): HeroStatus[K] - + /** * 计算主角的某个属性,包括百分比修正 * @example core.getRealStatus('atk'); // 计算主角的攻击力,包括百分比修正。战斗使用的就是这个值 * @param name 属性的英文名,请注意只能用于数值类属性哦,否则乘法会得到NaN */ - getRealStatus(name: string): any + getRealStatus(name: K): HeroStatus[K] /** 获得某个状态的名字 */ - getStatusLabel(name: string): string - + getStatusLabel(name: K): string + /** * 设置主角某个属性的百分比修正倍率,初始值为1, * 倍率存放在flag: '__'+name+'_buff__' 中 @@ -457,30 +517,30 @@ declare class control { * @param name 属性的英文名,请注意只能用于数值类属性哦,否则随后的乘法会得到NaN * @param value 新的百分比修正倍率,不填(效果上)视为1 */ - setBuff(name: string, value?: number): void - + setBuff(name: K, value?: HeroStatus[K]): void + /** * 增减主角某个属性的百分比修正倍率,加减法叠加和抵消。等价于 core.setBuff(name, core.getBuff(name) + value) * @example core.addBuff('atk', -0.1); // 主角获得一层“攻击力减一成”的负面效果 * @param name 属性的英文名,请注意只能用于数值类属性哦,否则随后的乘法会得到NaN * @param value 倍率的增量 */ - addBuff(name: string, value: number): void - + addBuff(name: K, value: HeroStatus[K]): void + /** * 读取主角某个属性的百分比修正倍率,初始值为1 * @example core.getBuff('atk'); // 主角当前能发挥出多大比例的攻击力 * @param name 属性的英文名 */ - getBuff(name: string): number + getBuff(name: HeroStatus[K]): number /** * 获得或移除毒衰咒效果 * @param action 获得还是移除,'get'为获得,'remove'为移除 * @param type 要获得或移除的毒衰咒效果 */ - triggerDebuff(action: string, type: string|string[]): void - + triggerDebuff(action: string, type: string | string[]): void + /** * 设置勇士位置 * 值得注意的是,这句话虽然会使勇士改变位置,但并不会使界面重新绘制; @@ -492,7 +552,7 @@ declare class control { */ setHeroLoc(name: 'x' | 'y', value: number, noGather?: boolean): void setHeroLoc(name: 'direction', value: direction, noGather?: boolean): void - + /** * 读取主角的位置和/或朝向 * @example core.getHeroLoc(); // 读取主角的位置和朝向 @@ -502,7 +562,7 @@ declare class control { getHeroLoc(): { x: number, y: number, direction: direction } getHeroLoc(name: 'x' | 'y'): number getHeroLoc(name: 'direction'): direction - + /** * 根据级别的数字获取对应的名称,后者定义在全塔属性 * @example core.getLvName(); // 获取主角当前级别的名称,如“下级佣兵” @@ -510,13 +570,13 @@ declare class control { * @returns 级别的名称,如果不存在就还是返回数字 */ getLvName(lv?: number): string | number - + /** * 获得下次升级需要的经验值。 * 升级扣除模式下会返回经验差值;非扣除模式下会返回总共需要的经验值。 * 如果无法进行下次升级,返回null。 */ - getNextLvUpNeed() : number + getNextLvUpNeed(): number /** * 设置一个flag变量 @@ -525,7 +585,7 @@ declare class control { * @param value 变量的新值,不填或填null视为删除 */ setFlag(name: string, value?: any): void - + /** * 增减一个flag变量,等价于 core.setFlag(name, core.getFlag(name, 0) + value) * @example core.addFlag('hatred', 1); // 增加1点仇恨值 @@ -533,7 +593,7 @@ declare class control { * @param value 变量的增量 */ addFlag(name: string, value: number | string): void - + /** * 读取一个flag变量 * @param name 变量名,支持中文 @@ -541,7 +601,7 @@ declare class control { * @returns flags[name] ?? defaultValue */ getFlag(name: string, defaultValue?: any): any - + /** * 判定一个flag变量是否存在且不为false、0、''、null、undefined和NaN * @example core.hasFlag('poison'); // 判断主角当前是否中毒 @@ -549,20 +609,20 @@ declare class control { * @returns !!core.getFlag(name) */ hasFlag(name: string): boolean - + /** * 设置天气,不计入存档。如需长期生效请使用core.events._action_setWeather()函数 * @example core.setWeather('fog', 10); // 设置十级大雾天 * @param type 新天气的类型,不填视为无天气 * @param level 新天气(晴天除外)的级别,必须为不大于10的正整数,不填视为5 */ - setWeather(type?: 'rain' | 'snow' | 'sun' | 'fog' | 'cloud', level?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10): void - + setWeather(type?: 'rain' | 'snow' | 'sun' | 'fog' | 'cloud' | string, level?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10): void + /** 注册一个天气 */ registerWeather(name: string, initFunc: (level: number) => void, frameFunc?: (timestamp: number, level: number) => void): void /** 注销一个天气 */ - unregisterWeather(name: string) : void; + unregisterWeather(name: string): void; /** * 更改画面色调,不计入存档。如需长期生效请使用core.events._action_setCurtain()函数 @@ -572,7 +632,7 @@ declare class control { * @param callback 更改完毕后的回调函数,可选。事件流中常取core.doAction */ setCurtain(color?: [number, number, number, number?], time?: number, moveMode?: string, callback?: () => void): void - + /** * 画面闪烁 * @example core.screenFlash([255, 0, 0, 1], 3); // 红屏一闪而过 @@ -581,8 +641,8 @@ declare class control { * @param times 闪烁的总次数,不填或填0都视为1 * @param callback 闪烁全部完毕后的回调函数,可选 */ - screenFlash(color: [number, number, number, number], time: number, times?: number, moveMode?: string, callback?: () => void): void - + screenFlash(color: [number, number, number, number?], time: number, times?: number, moveMode?: string, callback?: () => void): void + /** * 播放背景音乐,中途开播但不计入存档且只会持续到下次场景切换。如需长期生效请将背景音乐的文件名赋值给flags.__bgm__ * @example core.playBgm('bgm.mp3', 30); // 播放bgm.mp3,并跳过前半分钟 @@ -596,7 +656,7 @@ declare class control { * @param name 名称,可用来作为注销使用 * @param needPlaying 是否只在游戏运行时才执行(在标题界面不执行) * @param func 要执行的函数,或插件中的函数名;可接受timestamp(从页面加载完毕到当前所经过的时间)作为参数 - */ + */ registerAnimationFrame(name: string, needPlaying: boolean, func?: (timestamp: number) => void): void /** 注销一个animationFrame */ @@ -841,7 +901,7 @@ declare class events { * @param callback 回调函数,可选 */ startGame(hard: string, seed: number, route: string, callback?: () => void): void - + /** * 游戏结束 * @example core.gameOver(); // 游戏失败 @@ -850,7 +910,7 @@ declare class events { * @param norank true表示不计入榜单,可选 */ gameOver(ending?: string, fromReplay?: boolean, norank?: boolean): void - + /** * 战斗,如果填写了坐标就会删除该点的敌人并触发战后事件 * @example core.battle('greenSlime'); // 和从天而降的绿头怪战斗(如果打得过) @@ -861,7 +921,7 @@ declare class events { * @param callback 回调函数,可选 */ battle(id: string, x?: number, y?: number, force?: boolean, callback?: () => void): void - + /** * 开门(包括三种基础墙) * @example core.openDoor(0, 0, true, core.jumpHero); // 打开左上角的门,需要钥匙,然后主角原地跳跃半秒 @@ -871,7 +931,7 @@ declare class events { * @param callback 门完全打开后或打不开时的回调函数,可选 */ openDoor(x: number, y: number, needKey?: boolean, callback?: () => void): void - + /** * 获得道具并提示,如果填写了坐标就会删除该点的该道具 * @example core.getItem('book'); // 获得敌人手册并提示 @@ -882,7 +942,7 @@ declare class events { * @param callback 回调函数,可选 */ getItem(id: string, num?: number, x?: number, y?: number, callback?: () => void): void - + /** * 场景切换 * @example core.changeFloor('MT0'); // 传送到主塔0层,主角坐标和朝向不变,黑屏时间取用户设置值 @@ -893,14 +953,14 @@ declare class events { * @param callback 黑屏结束后的回调函数,可选 */ changeFloor(floorId: string, stair?: string, heroLoc?: { x?: number, y?: number, direction?: direction }, time?: number, callback?: () => void): void - + /** * 执行下一个事件指令,常作为回调 * @example core.setCurtain([0,0,0,1], undefined, null, core.doAction); // 事件中的原生脚本,配合勾选“不自动执行下一个事件”来达到此改变色调只持续到下次场景切换的效果 * @param keepUI true表示不清除UI画布和选择光标 */ doAction(keepUI?: true): void - + /** * 插入一段事件;此项不可插入公共事件,请用 core.insertCommonEvent * @example core.insertAction('一段文字'); // 插入一个显示文章 @@ -910,8 +970,8 @@ declare class events { * @param callback 新的回调函数,可选 * @param addToLast 插入的位置,true表示插入到末尾,否则插入到开头 */ - insertAction(action: string | MotaAction | MotaAction[], x?: number, y?: number, callback?: () => void, addToLast?: boolean): void - + insertAction(action: Events, x?: number, y?: number, callback?: () => void, addToLast?: boolean): void + /** * 设置一项敌人属性并计入存档 * @example core.setEnemy('greenSlime', 'def', 0); // 把绿头怪的防御设为0 @@ -922,7 +982,7 @@ declare class events { * @param prefix 独立开关前缀,一般不需要,下同 */ setEnemy(id: string, name: K, value?: Enemy[K], operator?: string, prefix?: string): void - + /** 设置某个点的敌人属性 */ setEnemyOnPoint(x: number, y: number, floorId: string, name: K, value?: Enemy[K], operator?: string, prefix?: string): void @@ -941,7 +1001,7 @@ declare class events { * @param prefix 独立开关前缀,一般不需要,下同 */ setFloorInfo(name: K, values?: Floor[K] | boolean | number | string | [number, number] | [string, number?] | Array, floorId?: string, prefix?: string): void - + /** * 设置一个系统开关 * @example core.setGlobalFlag('steelDoorWithoutKey', true); // 使全塔的所有铁门都不再需要钥匙就能打开 @@ -949,7 +1009,7 @@ declare class events { * @param value 开关的新值,您可以用!core.flags[name]简单地表示将此开关反转 */ setGlobalFlag(name: keyof SystemFlags, value: boolean): void - + /** * 关门,目标点必须为空地 * @example core.closeDoor(0, 0, 'yellowWall', core.jumpHero); // 在左上角关掉一堵黄墙,然后主角原地跳跃半秒 @@ -959,7 +1019,7 @@ declare class events { * @param callback 门完全关上后的回调函数,可选 */ closeDoor(x: number, y: number, id: string, callback?: () => void): void - + /** * 显示一张图片 * @example core.showImage(1, core.material.images.images['winskin.png'], [0,0,128,128], [0,0,416,416], 0.5, 1000); // 裁剪winskin.png的最左边128×128px,放大到铺满整个视野,1秒内淡入到50%透明,编号为1 @@ -972,7 +1032,7 @@ declare class events { * @param callback 图片完全显示出来后的回调函数,可选 */ showImage(code: number, image: string | HTMLImageElement, sloc?: Array, loc?: Array, opacityVal?: number, time?: number, callback?: () => void): void - + /** * 隐藏一张图片 * @example core.hideImage(1, 1000, core.jumpHero); // 1秒内淡出1号图片,然后主角原地跳跃半秒 @@ -981,7 +1041,7 @@ declare class events { * @param callback 图片完全消失后的回调函数,可选 */ hideImage(code: number, time?: number, callback?: () => void): void - + /** * 移动一张图片并/或改变其透明度 * @example core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明 @@ -1016,7 +1076,7 @@ declare class events { * @param y 动图在视野中的左上角纵坐标 */ showGif(name?: string, x?: number, y?: number): void - + /** * 调节bgm的音量 * @example core.setVolume(0, 100, core.jumpHero); // 0.1秒内淡出bgm,然后主角原地跳跃半秒 @@ -1025,7 +1085,7 @@ declare class events { * @param callback 渐变完成后的回调函数,可选 */ setVolume(value: number, time?: number, callback?: () => void): void - + /** * 视野抖动 * @example core.vibrate(); // 视野左右抖动1秒 @@ -1045,7 +1105,7 @@ declare class events { * @param callback 移动完毕后的回调函数,可选 */ eventMoveHero(steps: step[], time?: number, callback?: () => void): void - + /** * 主角跳跃,跳跃勇士。ex和ey为目标点的坐标,可以为null表示原地跳跃。time为总跳跃时间。 * @example core.jumpHero(); // 主角原地跳跃半秒 @@ -1055,7 +1115,7 @@ declare class events { * @param callback 跳跃完毕后的回调函数,可选 */ jumpHero(ex?: number, ey?: number, time?: number, callback?: () => void): void - + /** * 更改主角行走图 * @example core.setHeroIcon('npc48.png', true); // 把主角从阳光变成样板0层左下角的小姐姐,但不立即刷新 @@ -1063,7 +1123,7 @@ declare class events { * @param noDraw true表示不立即刷新(刷新会导致大地图下视野重置到以主角为中心) */ setHeroIcon(name: string, noDraw?: boolean): void - + /** * 尝试使用一个道具 * @example core.tryUseItem('pickaxe'); // 尝试使用破墙镐 @@ -1072,7 +1132,7 @@ declare class events { tryUseItem(itemId: string): void /** 初始化游戏 */ - resetGame(hero?: any, hard?: any, floorId?: string, maps?: any, values?: any): void + resetGame(hero?: HeroStatus, hard?: any, floorId?: string, maps?: any, values?: any): void /** 游戏获胜事件 */ win(reason?: string, norank?: boolean, noexit?: boolean): void @@ -1468,7 +1528,7 @@ declare class maps { * @returns 图块的数字,定义在project\maps.js(请注意和project\icons.js中的“图块索引”相区分!) */ getNumberById(id: string): number - + /** * 生成事件层矩阵 * @example core.getMapArray('MT0'); // 生成主塔0层的事件层矩阵,隐藏的图块视为0 @@ -1480,7 +1540,7 @@ declare class maps { /** 判定图块的事件层数字;不存在为0 */ getMapNumber(floorId?: string, noCache?: boolean): number - + /** * 生成背景层矩阵 * @example core.getBgMapArray('MT0'); // 生成主塔0层的背景层矩阵,使用缓存 @@ -1489,7 +1549,7 @@ declare class maps { * @returns 背景层矩阵,注意对其阵元的访问是[y][x] */ getBgMapArray(floorId?: string, noCache?: boolean): number[][] - + /** * 生成前景层矩阵 * @example core.getFgMapArray('MT0'); // 生成主塔0层的前景层矩阵,使用缓存 @@ -1498,7 +1558,7 @@ declare class maps { * @returns 前景层矩阵,注意对其阵元的访问是[y][x] */ getFgMapArray(floorId?: string, noCache?: boolean): number[][] - + /** * 判定背景层的一个位置是什么 * @example core.getBgNumber(); // 判断主角脚下的背景层图块的数字 @@ -1508,7 +1568,7 @@ declare class maps { * @param 可选,true表示不使用缓存而强制重算 */ getBgNumber(x?: number, y?: number, floorId?: string, noCache?: boolean): number - + /** * 判定前景层的一个位置是什么 * @example core.getFgNumber(); // 判断主角脚下的前景层图块的数字 @@ -1518,7 +1578,7 @@ declare class maps { * @param 可选,true表示不使用缓存而强制重算 */ getFgNumber(x?: number, y?: number, floorId?: string, noCache?: boolean): number - + /** * 可通行性判定 * @example core.generateMovableArray(); // 判断当前地图主角从各点能向何方向移动 @@ -1526,7 +1586,7 @@ declare class maps { * @returns 从各点可移动方向的三维数组 */ generateMovableArray(floorId?: string): Array>> - + /** * 单点单朝向的可通行性判定 * @exmaple core.canMoveHero(); // 判断主角是否可以前进一步 @@ -1537,7 +1597,7 @@ declare class maps { * @returns true表示可移动,false表示不可移动 */ canMoveHero(x?: number, y?: number, direction?: direction, floorId?: string): boolean - + /** * 能否瞬移到某点,并求出节约的步数。 * @example core.canMoveDirectly(0, 0); // 能否瞬移到地图左上角 @@ -1546,7 +1606,7 @@ declare class maps { * @returns 正数表示节约的步数,-1表示不可瞬移 */ canMoveDirectly(destX: number, destY: number): number - + /** * 自动寻路 * @example core.automaticRoute(0, 0); // 自动寻路到地图左上角 @@ -1555,7 +1615,7 @@ declare class maps { * @returns 每步走完后主角的loc属性组成的一维数组 */ automaticRoute(destX: number, destY: number): Array<{ direction: direction, x: number, y: number }> - + /** * 地图重绘 * @example core.drawMap(); // 重绘当前地图,常用于更改贴图后或自动元件的刷新 @@ -1563,7 +1623,7 @@ declare class maps { * @param callback 重绘完毕后的回调函数,可选 */ drawMap(floorId?: string, callback?: () => void): void - + /** * 绘制背景层(含贴图,其与背景层矩阵的绘制顺序可通过复写此函数来改变) * @example core.drawBg(); // 绘制当前地图的背景层 @@ -1571,7 +1631,7 @@ declare class maps { * @param ctx 某画布的ctx,用于绘制缩略图,一般不需要 */ drawBg(floorId?: string, ctx?: CanvasRenderingContext2D): void - + /** * 绘制事件层 * @example core.drawEvents(); // 绘制当前地图的事件层 @@ -1580,7 +1640,7 @@ declare class maps { * @param ctx 某画布的ctx,用于绘制缩略图,一般不需要 */ drawEvents(floorId?: string, blocks?: Block[], ctx?: CanvasRenderingContext2D): void - + /** * 绘制前景层(含贴图,其与前景层矩阵的绘制顺序可通过复写此函数来改变) * @example core.drawFg(); // 绘制当前地图的前景层 @@ -1588,7 +1648,7 @@ declare class maps { * @param ctx 某画布的ctx,用于绘制缩略图,一般不需要 */ drawFg(floorId?: string, ctx?: CanvasRenderingContext2D): void - + /** * 绘制缩略图 * @example core.drawThumbnail(); // 绘制当前地图的缩略图 @@ -1597,7 +1657,7 @@ declare class maps { * @param options 额外的绘制项,可选。可以增绘主角位置和朝向、采用不同于游戏中的主角行走图、增绘显伤、提供flags用于存读档 */ drawThumbnail(floorId?: string, blocks?: Block[], options?: object): void - + /** * 判定某个点是否不可被踏入(不基于主角生命值和图块cannotIn属性) * @example core.noPass(0, 0); // 判断地图左上角能否被踏入 @@ -1607,7 +1667,7 @@ declare class maps { * @returns true表示可踏入 */ noPass(x: number, y: number, floorId?: string): boolean - + /** * 判定某个点的图块id * @example if(core.getBlockId(x1, y1) != 'greenSlime' && core.getBlockId(x2, y2) != 'redSlime') core.openDoor(x3, y3); // 一个简单的机关门事件,打败或炸掉这一对绿头怪和红头怪就开门 @@ -1618,7 +1678,7 @@ declare class maps { * @returns 图块id,该点无图块则返回null */ getBlockId(x: number, y: number, floorId?: string, showDisable?: boolean): string | null - + /** 判定某个点的图块数字;空图块为0 */ getBlockNumber(x: number, y: number, floorId?: string, showDisable?: boolean): number @@ -1632,7 +1692,7 @@ declare class maps { * @returns 图块类型,即“地形、四帧动画、矮敌人、高敌人、道具、矮npc、高npc、自动元件、额外地形”之一 */ getBlockCls(x: number, y: number, floorId?: string, showDisable?: boolean): 'terrains' | 'animates' | 'enemys' | 'enemy48' | 'items' | 'npcs' | 'npc48' | 'autotile' | 'tileset' | null - + /** * 搜索图块, 支持通配符 * @example core.searchBlock('*Door'); // 搜索当前地图的所有门 @@ -1641,8 +1701,8 @@ declare class maps { * @param showDisable 隐藏点是否计入,true表示计入 * @returns 一个详尽的数组,一般只用到其长度 */ - searchBlock(id: string, floorId?: string|Array, showDisable?: boolean): Array<{ floorId: string, index: number, x: number, y: number, block: Block }> - + searchBlock(id: string, floorId?: string | Array, showDisable?: boolean): Array<{ floorId: string, index: number, x: number, y: number, block: Block }> + /** * 根据给定的筛选函数搜索全部满足条件的图块 * @example core.searchBlockWithFilter(function (block) { return block.event.id.endsWith('Door'); }); // 搜索当前地图的所有门 @@ -1651,7 +1711,7 @@ declare class maps { * @param showDisable 隐藏点是否计入,true表示计入 * @returns 一个详尽的数组 */ - searchBlockWithFilter(blockFilter: (Block) => boolean, floorId?: string|Array, showDisable?: boolean): Array<{ floorId: string, index: number, x: number, y: number, block: Block }> + searchBlockWithFilter(blockFilter: (Block) => boolean, floorId?: string | Array, showDisable?: boolean): Array<{ floorId: string, index: number, x: number, y: number, block: Block }> /** * 显示(隐藏或显示的)图块,此函数将被“显示事件”指令和勾选了“不消失”的“移动/跳跃事件”指令(如阻击怪)的终点调用 @@ -1661,7 +1721,7 @@ declare class maps { * @param floorId 地图id,不填视为当前地图 */ showBlock(x: number, y: number, floorId?: string): void - + /** * 隐藏一个图块,对应于「隐藏事件」且不删除 * @example core.hideBlock(0, 0); // 隐藏地图左上角的图块 @@ -1670,7 +1730,7 @@ declare class maps { * @param floorId 地图id,不填视为当前地图 */ hideBlock(x: number, y: number, floorId?: string): void - + /** * 删除一个图块,对应于「隐藏事件」并同时删除 * @example core.removeBlock(0, 0); // 尝试删除地图左上角的图块 @@ -1679,7 +1739,7 @@ declare class maps { * @param floorId 地图id,不填视为当前地图 */ removeBlock(x: number, y: number, floorId?: string): void - + /** * 显隐背景/前景层图块 * @example core.maps._triggerBgFgMap('show', 'fg', [0, 0]); // 显示地图左上角的前景层图块 @@ -1690,7 +1750,7 @@ declare class maps { * @param callback 显隐完毕后的回调函数,可选 */ //_triggerBgFgMap(type: 'show' | 'hide', name: 'bg' | 'fg', loc: [number, number] | Array<[number, number]>, floorId?: string, callback?: () => void): void - + /** * 显隐楼层贴图 * @example core.maps._triggerFloorImage('show', [0, 0]); // 显示当前地图以左上角为左上角的贴图 @@ -1700,7 +1760,7 @@ declare class maps { * @param callback 显隐完毕后的回调函数,可选 */ //_triggerFloorImage(type: 'show' | 'hide', loc: [number, number] | Array<[number, number]>, floorId?: string, callback?: () => void): void - + /** * 转变图块 * @example core.setBlock(1, 0, 0); // 把地图左上角变成黄墙 @@ -1710,7 +1770,7 @@ declare class maps { * @param floorId 地图id,不填视为当前地图 */ setBlock(number: number | string, x: number, y: number, floorId?: string): void - + /** * 批量替换图块 * @example core.replaceBlock(21, 22, core.floorIds); // 把游戏中地上当前所有的黄钥匙都变成蓝钥匙 @@ -1719,7 +1779,7 @@ declare class maps { * @param floorId 地图id或其数组,不填视为当前地图 */ replaceBlock(fromNumber: number, toNumber: number, floorId?: string | Array): void - + /** * 转变图层块 * @example core.setBgFgBlock('bg', 167, 6, 6); // 把当前地图背景层的中心块改为滑冰 @@ -1730,7 +1790,7 @@ declare class maps { * @param floorId 地图id,不填视为当前地图 */ setBgFgBlock(name: 'bg' | 'fg', number: number | string, x: number, y: number, floorId?: string): void - + /** * 移动图块 * @example core.moveBlock(0, 0, ['down']); // 令地图左上角的图块下移一格,用时半秒,再花半秒淡出 @@ -1742,7 +1802,7 @@ declare class maps { * @param callback 移动或淡出后的回调函数,可选 */ moveBlock(x: number, y: number, steps: step[], time?: number, keep?: boolean, callback?: () => void): void - + /** * 跳跃图块;从V2.7开始不再有音效 * @example core.jumpBlock(0, 0, 0, 0); // 令地图左上角的图块原地跳跃半秒,再花半秒淡出 @@ -1755,7 +1815,7 @@ declare class maps { * @param callback 落地或淡出后的回调函数,可选 */ jumpBlock(sx: number, sy: number, ex: number, ey: number, time?: number, keep?: boolean, callback?: () => void): void - + /** * 播放动画,注意即使指定了主角的坐标也不会跟随主角移动,如有需要请使用core.drawHeroAnimate(name, callback)函数 * @example core.drawAnimate('attack', core.nextX(), core.nextY(), false, core.vibrate); // 在主角面前一格播放普攻动画,动画停止后视野左右抖动1秒 @@ -1781,10 +1841,10 @@ declare class maps { * @param id 播放动画的编号,即drawAnimate或drawHeroAnimate返回值 * @param doCallback 是否执行该动画的回调函数 */ - stopAnimate(id?: number, doCallback?: boolean): void + stopAnimate(id?: number, doCallback?: boolean): void /** 获得当前正在播放的所有(指定)动画的id列表 */ - getPlayingAnimates(name?: string) : Array + getPlayingAnimates(name?: string): Array /** 加载某个楼层(从剧本或存档中) */ loadFloor(floorId?: string, map?: any): any @@ -1910,7 +1970,7 @@ declare class maps { /** @file loader.js 主要负责资源的加载 */ declare class loader { /** 加载一系列图片 */ - loadImages(dir: any, names: any, toSave: any, callback?: () => any) : any + loadImages(dir: any, names: any, toSave: any, callback?: () => any): any /** 加载某一张图片 */ loadImage(dir: any, imgName?: any, callback?: () => any): any @@ -2055,7 +2115,7 @@ declare class items { * @param beComparedEquipId 装备乙的id * @returns 两装备的各属性差,甲减乙,0省略 */ - compareEquipment(compareEquipId: string, beComparedEquipId: string): { [key: string]: number} + compareEquipment(compareEquipId: string, beComparedEquipId: string): { [key: string]: number } /** * 保存当前套装 @@ -2090,7 +2150,7 @@ declare class items { * @param operator 操作符,可选,如+=表示在原始值上增加 * @param prefix 独立开关前缀,一般不需要 */ - setEquip(equipId: string, valueType: string, name: string, value: any, operator?: string, prefix?: string): void + setEquip(equipId: string, valueType: string, name: string, value: any, operator?: string, prefix?: string): void } /** @file ui.js 主要用来进行UI窗口的绘制,如对话框、怪物手册、楼传器、存读档界面等等。*/ @@ -2246,7 +2306,7 @@ declare class ui { drawUIEventSelector(code: number, background: string, x: number, y: number, w: number, h: number, z?: number): void /** 清除一个或多个选择光标 */ - clearUIEventSelector(code: number|number[]): void + clearUIEventSelector(code: number | number[]): void /** 绘制一个确认框 */ drawConfirmBox(text: string, yesCallback?: () => void, noCallback?: () => void): void @@ -2265,7 +2325,7 @@ declare class ui { * left, top:起始点位置;maxWidth:单行最大宽度;color:默认颜色;align:左中右 * fontSize:字体大小;lineHeight:行高;time:打字机间隔;font:默认字体名 * @returns 绘制信息 - */ + */ drawTextContent(ctx: string | CanvasRenderingContext2D, content: string, config: any): any /** 获得某段文字的预计绘制高度;参见 drawTextContent */ @@ -2412,7 +2472,7 @@ declare class utils { clone(data?: T, filter?: (name: string, value: any) => boolean, recursion?: boolean): T /** 深拷贝一个1D或2D的数组 */ - cloneArray(data?: Array|Array>): Array|Array> + cloneArray(data?: Array | Array>): Array | Array> /** * 等比例切分一张图片 @@ -2557,7 +2617,7 @@ declare class utils { * @exmaple 1 + core.rand2(6); // 随机生成一个小于7的正整数,模拟骰子的效果 * @param num 正整数,0或不填会被视为2147483648 * @returns 属于 [0, num) 的随机数 - */ + */ rand2(num?: number): number /** @@ -2601,7 +2661,7 @@ declare class utils { * 尝试复制一段文本到剪切板。 */ copy(data: string): void - + /** * 发送一个HTTP请求 [异步] * @param type 请求类型