From 81f681542965670fa9c3d8379a723ed1b56c9aae Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 16 Apr 2023 17:05:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E8=BD=AC=E4=B8=BAes=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idea.md | 4 +- package.json | 7 +- pnpm-lock.yaml | 11 +- public/project/plugin/fiveLayer.js | 388 ++- public/project/plugin/halo.js | 95 +- public/project/plugin/hero.js | 155 +- public/project/plugin/heroFourFrames.js | 110 +- public/project/plugin/hotReload.js | 2 +- public/project/plugin/index.js | 32 + public/project/plugin/itemDetail.js | 238 +- public/project/plugin/loopMap.js | 424 ++-- public/project/plugin/popup.js | 236 +- public/project/plugin/remainEnemy.js | 128 +- public/project/plugin/removeMap.js | 221 +- public/project/plugin/replay.js | 164 +- public/project/plugin/shop.js | 127 +- public/project/plugin/skillTree.js | 612 +++-- public/project/plugin/skills.js | 313 ++- public/project/plugin/study.js | 139 +- public/project/plugin/towerBoss.js | 3090 +++++++++++------------ public/project/plugin/ui.js | 2 +- public/project/plugin/utils.js | 91 +- script/{compress.ts => build.ts} | 51 +- src/plugin/settings.ts | 2 + src/plugin/shadow/gameShadow.ts | 14 +- 25 files changed, 3265 insertions(+), 3391 deletions(-) create mode 100644 public/project/plugin/index.js rename script/{compress.ts => build.ts} (76%) diff --git a/idea.md b/idea.md index 048b0bf..4deaf1c 100644 --- a/idea.md +++ b/idea.md @@ -28,14 +28,14 @@ #### 技能 -闪避:每 M 回合闪避一次,减少 N%的伤害 +闪避:每 M 回合闪避一次,减少 N% 的伤害 ## 机制 ### 通用 - 实时天气 -- 成就系统 +- 成就系统(完成) - 装备合成、装备(孔)强化 - 宝石目标设定 - 自动宝物规划,选中两个或更多宝物后自动在本地图中规划出最优拾取路线,原则是尽量减少其余宝物的捡拾,自动切换主动技能,怪物造成的伤害最低的路线 diff --git a/package.json b/package.json index 995a834..90eee62 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vue-tsc && vite build && ts-node-esm script/compress.ts", - "build-gh": "vue-tsc && vite build --base=/HumanBreak/ && ts-node-esm script/compress.ts", - "build-local": "vue-tsc && vite build --base=/ && ts-node-esm script/compress.ts", + "build": "vue-tsc && vite build && ts-node-esm script/build.ts", + "build-gh": "vue-tsc && vite build --base=/HumanBreak/ && ts-node-esm script/build.ts", + "build-local": "vue-tsc && vite build --base=/ && ts-node-esm script/build.ts", "preview": "vite preview", "preview-node": "cd dist && node server.cjs", "update": "ts-node-esm script/update.ts", @@ -42,6 +42,7 @@ "form-data": "^4.0.0", "fs-extra": "^10.1.0", "less": "^4.1.3", + "rollup": "^3.20.2", "terser": "^5.16.9", "ts-node": "^10.9.1", "typescript": "^4.9.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d3f7ef..3081cbf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,7 @@ specifiers: lodash: ^4.17.21 lz-string: ^1.5.0 mutate-animate: ^1.1.1 + rollup: ^3.20.2 terser: ^5.16.9 three: ^0.149.0 ts-node: ^10.9.1 @@ -61,10 +62,11 @@ devDependencies: form-data: 4.0.0 fs-extra: 10.1.0 less: 4.1.3 + rollup: 3.20.2 terser: 5.16.9 ts-node: 10.9.1_o6avl3oodj6mwqsx3rm2wfkgv4 typescript: 4.9.5 - unplugin-vue-components: 0.22.12_vue@3.2.47 + unplugin-vue-components: 0.22.12_rollup@3.20.2+vue@3.2.47 vite: 4.2.1_lu7yuwtv4qfbkrotoux232iypi vue-tsc: 1.2.0_typescript@4.9.5 @@ -1620,7 +1622,7 @@ packages: rimraf: 3.0.2 dev: true - /@rollup/pluginutils/5.0.2: + /@rollup/pluginutils/5.0.2_rollup@3.20.2: resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1632,6 +1634,7 @@ packages: '@types/estree': 1.0.0 estree-walker: 2.0.2 picomatch: 2.3.1 + rollup: 3.20.2 dev: true /@simonwep/pickr/1.8.2: @@ -4399,7 +4402,7 @@ packages: engines: {node: '>= 10.0.0'} dev: true - /unplugin-vue-components/0.22.12_vue@3.2.47: + /unplugin-vue-components/0.22.12_rollup@3.20.2+vue@3.2.47: resolution: {integrity: sha512-FxyzsuBvMCYPIk+8cgscGBQ345tvwVu+qY5IhE++eorkyvA4Z1TiD/HCiim+Kbqozl10i4K+z+NCa2WO2jexRA==} engines: {node: '>=14'} peerDependencies: @@ -4410,7 +4413,7 @@ packages: optional: true dependencies: '@antfu/utils': 0.7.2 - '@rollup/pluginutils': 5.0.2 + '@rollup/pluginutils': 5.0.2_rollup@3.20.2 chokidar: 3.5.3 debug: 4.3.4 fast-glob: 3.2.12 diff --git a/public/project/plugin/fiveLayer.js b/public/project/plugin/fiveLayer.js index 948d90f..7efa072 100644 --- a/public/project/plugin/fiveLayer.js +++ b/public/project/plugin/fiveLayer.js @@ -1,208 +1,198 @@ /// -'use strict'; +export {}; -(function () { - // 创建新图层 - function createCanvas(name, zIndex) { - if (!name) return; - var canvas = document.createElement('canvas'); - canvas.id = name; - canvas.className = 'gameCanvas'; - // 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高 - if (main.mode != 'editor') canvas.style.zIndex = zIndex || 0; - // 将图层插入进游戏内容 - document.getElementById('gameDraw').appendChild(canvas); - var ctx = canvas.getContext('2d'); - core.canvas[name] = ctx; +// 创建新图层 +function createCanvas(name, zIndex) { + if (!name) return; + var canvas = document.createElement('canvas'); + canvas.id = name; + canvas.className = 'gameCanvas'; + // 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高 + if (main.mode != 'editor') canvas.style.zIndex = zIndex || 0; + // 将图层插入进游戏内容 + document.getElementById('gameDraw').appendChild(canvas); + var ctx = canvas.getContext('2d'); + core.canvas[name] = ctx; - return canvas; + return canvas; +} + +var bg2Canvas = createCanvas('bg2', 20); +var fg2Canvas = createCanvas('fg2', 63); +// 大地图适配 +core.bigmap.canvas = ['bg2', 'fg2', 'bg', 'event', 'event2', 'fg', 'damage']; +core.initStatus.bg2maps = {}; +core.initStatus.fg2maps = {}; + +if (main.mode == 'editor') { + /*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/ + // 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层) + // 背景层2(bg2) 插入事件层(event)之前(即bg与event之间) + document + .getElementById('mapEdit') + .insertBefore(bg2Canvas, document.getElementById('event')); + // 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后) + document + .getElementById('mapEdit') + .insertBefore(fg2Canvas, document.getElementById('ebm')); + // 原本有三个图层 从4开始添加 + var num = 4; + // 新增图层存入editor.dom中 + editor.dom.bg2c = core.canvas.bg2.canvas; + editor.dom.bg2Ctx = core.canvas.bg2; + editor.dom.fg2c = core.canvas.fg2.canvas; + editor.dom.fg2Ctx = core.canvas.fg2; + editor.dom.maps.push('bg2map', 'fg2map'); + editor.dom.canvas.push('bg2', 'fg2'); + + // 创建编辑器上的按钮 + var createCanvasBtn = name => { + // 电脑端创建按钮 + var input = document.createElement('input'); + // layerMod4/layerMod5 + var id = 'layerMod' + num++; + // bg2map/fg2map + var value = name + 'map'; + input.type = 'radio'; + input.name = 'layerMod'; + input.id = id; + input.value = value; + editor.dom[id] = input; + input.onchange = () => { + editor.uifunctions.setLayerMod(value); + }; + return input; + }; + + var createCanvasBtn_mobile = name => { + // 手机端往选择列表中添加子选项 + var input = document.createElement('option'); + var id = 'layerMod' + num++; + var value = name + 'map'; + input.name = 'layerMod'; + input.value = value; + editor.dom[id] = input; + return input; + }; + if (!editor.isMobile) { + var input = createCanvasBtn('bg2'); + var input2 = createCanvasBtn('fg2'); + // 获取事件层及其父节点 + var child = document.getElementById('layerMod'), + parent = child.parentNode; + // 背景层2插入事件层前 + parent.insertBefore(input, child); + // 不能直接更改背景层2的innerText 所以创建文本节点 + var txt = document.createTextNode('背2'); + // 插入事件层前(即新插入的背景层2前) + parent.insertBefore(txt, child); + // 向最后插入前景层2(即插入前景层后) + parent.appendChild(input2); + var txt2 = document.createTextNode('前2'); + parent.appendChild(txt2); + } else { + var input = createCanvasBtn_mobile('bg2'); + var input2 = createCanvasBtn_mobile('fg2'); + // 手机端因为是选项 所以可以直接改innerText + input.innerText = '背景2'; + input2.innerText = '前景2'; + var parent = document.getElementById('layerMod'); + parent.insertBefore(input, parent.children[1]); + parent.appendChild(input2); } - - var bg2Canvas = createCanvas('bg2', 20); - var fg2Canvas = createCanvas('fg2', 63); - // 大地图适配 - core.bigmap.canvas = [ - 'bg2', - 'fg2', - 'bg', - 'event', - 'event2', - 'fg', - 'damage' +} +core.maps._loadFloor_doNotCopy = function () { + return [ + 'firstArrive', + 'eachArrive', + 'blocks', + 'parallelDo', + 'map', + 'bgmap', + 'fgmap', + 'bg2map', + 'fg2map', + 'events', + 'changeFloor', + 'afterBattle', + 'afterGetItem', + 'afterOpenDoor', + 'cannotMove' ]; - core.initStatus.bg2maps = {}; - core.initStatus.fg2maps = {}; - - if (main.mode == 'editor') { - /*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/ - // 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层) - // 背景层2(bg2) 插入事件层(event)之前(即bg与event之间) - document - .getElementById('mapEdit') - .insertBefore(bg2Canvas, document.getElementById('event')); - // 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后) - document - .getElementById('mapEdit') - .insertBefore(fg2Canvas, document.getElementById('ebm')); - // 原本有三个图层 从4开始添加 - var num = 4; - // 新增图层存入editor.dom中 - editor.dom.bg2c = core.canvas.bg2.canvas; - editor.dom.bg2Ctx = core.canvas.bg2; - editor.dom.fg2c = core.canvas.fg2.canvas; - editor.dom.fg2Ctx = core.canvas.fg2; - editor.dom.maps.push('bg2map', 'fg2map'); - editor.dom.canvas.push('bg2', 'fg2'); - - // 创建编辑器上的按钮 - var createCanvasBtn = name => { - // 电脑端创建按钮 - var input = document.createElement('input'); - // layerMod4/layerMod5 - var id = 'layerMod' + num++; - // bg2map/fg2map - var value = name + 'map'; - input.type = 'radio'; - input.name = 'layerMod'; - input.id = id; - input.value = value; - editor.dom[id] = input; - input.onchange = () => { - editor.uifunctions.setLayerMod(value); - }; - return input; - }; - - var createCanvasBtn_mobile = name => { - // 手机端往选择列表中添加子选项 - var input = document.createElement('option'); - var id = 'layerMod' + num++; - var value = name + 'map'; - input.name = 'layerMod'; - input.value = value; - editor.dom[id] = input; - return input; - }; - if (!editor.isMobile) { - var input = createCanvasBtn('bg2'); - var input2 = createCanvasBtn('fg2'); - // 获取事件层及其父节点 - var child = document.getElementById('layerMod'), - parent = child.parentNode; - // 背景层2插入事件层前 - parent.insertBefore(input, child); - // 不能直接更改背景层2的innerText 所以创建文本节点 - var txt = document.createTextNode('背2'); - // 插入事件层前(即新插入的背景层2前) - parent.insertBefore(txt, child); - // 向最后插入前景层2(即插入前景层后) - parent.appendChild(input2); - var txt2 = document.createTextNode('前2'); - parent.appendChild(txt2); - } else { - var input = createCanvasBtn_mobile('bg2'); - var input2 = createCanvasBtn_mobile('fg2'); - // 手机端因为是选项 所以可以直接改innerText - input.innerText = '背景2'; - input2.innerText = '前景2'; - var parent = document.getElementById('layerMod'); - parent.insertBefore(input, parent.children[1]); - parent.appendChild(input2); - } +}; +////// 绘制背景和前景层 ////// +core.maps._drawBg_draw = function (floorId, toDrawCtx, cacheCtx, config) { + config.ctx = cacheCtx; + core.maps._drawBg_drawBackground(floorId, config); + // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。 + core.maps._drawFloorImages( + floorId, + config.ctx, + 'bg', + null, + null, + config.onMap + ); + core.maps._drawBgFgMap(floorId, 'bg', config); + if (config.onMap) { + core.drawImage( + toDrawCtx, + cacheCtx.canvas, + core.bigmap.v2 ? -32 : 0, + core.bigmap.v2 ? -32 : 0 + ); + core.clearMap('bg2'); + core.clearMap(cacheCtx); } - core.maps._loadFloor_doNotCopy = function () { - return [ - 'firstArrive', - 'eachArrive', - 'blocks', - 'parallelDo', - 'map', - 'bgmap', - 'fgmap', - 'bg2map', - 'fg2map', - 'events', - 'changeFloor', - 'afterBattle', - 'afterGetItem', - 'afterOpenDoor', - 'cannotMove' - ]; - }; - ////// 绘制背景和前景层 ////// - core.maps._drawBg_draw = function (floorId, toDrawCtx, cacheCtx, config) { - config.ctx = cacheCtx; - core.maps._drawBg_drawBackground(floorId, config); - // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。 - core.maps._drawFloorImages( - floorId, - config.ctx, - 'bg', - null, - null, - config.onMap + core.maps._drawBgFgMap(floorId, 'bg2', config); + if (config.onMap) + core.drawImage( + 'bg2', + cacheCtx.canvas, + core.bigmap.v2 ? -32 : 0, + core.bigmap.v2 ? -32 : 0 ); - core.maps._drawBgFgMap(floorId, 'bg', config); - if (config.onMap) { - core.drawImage( - toDrawCtx, - cacheCtx.canvas, - core.bigmap.v2 ? -32 : 0, - core.bigmap.v2 ? -32 : 0 - ); - core.clearMap('bg2'); - core.clearMap(cacheCtx); - } - core.maps._drawBgFgMap(floorId, 'bg2', config); - if (config.onMap) - core.drawImage( - 'bg2', - cacheCtx.canvas, - core.bigmap.v2 ? -32 : 0, - core.bigmap.v2 ? -32 : 0 - ); - config.ctx = toDrawCtx; - }; - core.maps._drawFg_draw = function (floorId, toDrawCtx, cacheCtx, config) { - config.ctx = cacheCtx; - // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制前景图块;后绘制的覆盖先绘制的。 - core.maps._drawFloorImages( - floorId, - config.ctx, - 'fg', - null, - null, - config.onMap + config.ctx = toDrawCtx; +}; +core.maps._drawFg_draw = function (floorId, toDrawCtx, cacheCtx, config) { + config.ctx = cacheCtx; + // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制前景图块;后绘制的覆盖先绘制的。 + core.maps._drawFloorImages( + floorId, + config.ctx, + 'fg', + null, + null, + config.onMap + ); + core.maps._drawBgFgMap(floorId, 'fg', config); + if (config.onMap) { + core.drawImage( + toDrawCtx, + cacheCtx.canvas, + core.bigmap.v2 ? -32 : 0, + core.bigmap.v2 ? -32 : 0 ); - core.maps._drawBgFgMap(floorId, 'fg', config); - if (config.onMap) { - core.drawImage( - toDrawCtx, - cacheCtx.canvas, - core.bigmap.v2 ? -32 : 0, - core.bigmap.v2 ? -32 : 0 - ); - core.clearMap('fg2'); - core.clearMap(cacheCtx); - } - core.maps._drawBgFgMap(floorId, 'fg2', config); - if (config.onMap) - core.drawImage( - 'fg2', - cacheCtx.canvas, - core.bigmap.v2 ? -32 : 0, - core.bigmap.v2 ? -32 : 0 - ); - config.ctx = toDrawCtx; + core.clearMap('fg2'); + core.clearMap(cacheCtx); + } + core.maps._drawBgFgMap(floorId, 'fg2', config); + if (config.onMap) + core.drawImage( + 'fg2', + cacheCtx.canvas, + core.bigmap.v2 ? -32 : 0, + core.bigmap.v2 ? -32 : 0 + ); + config.ctx = toDrawCtx; +}; +////// 移动判定 ////// +core.maps._generateMovableArray_arrays = function (floorId) { + return { + bgArray: this.getBgMapArray(floorId), + fgArray: this.getFgMapArray(floorId), + eventArray: this.getMapArray(floorId), + bg2Array: this._getBgFgMapArray('bg2', floorId), + fg2Array: this._getBgFgMapArray('fg2', floorId) }; - ////// 移动判定 ////// - core.maps._generateMovableArray_arrays = function (floorId) { - return { - bgArray: this.getBgMapArray(floorId), - fgArray: this.getFgMapArray(floorId), - eventArray: this.getMapArray(floorId), - bg2Array: this._getBgFgMapArray('bg2', floorId), - fg2Array: this._getBgFgMapArray('fg2', floorId) - }; - }; -})(); +}; diff --git a/public/project/plugin/halo.js b/public/project/plugin/halo.js index 99c6ed1..239e089 100644 --- a/public/project/plugin/halo.js +++ b/public/project/plugin/halo.js @@ -1,57 +1,54 @@ /// -'use strict'; -(function () { - /** - * 绘制光环范围 - * @param {CanvasRenderingContext2D} ctx - * @param {boolean} onMap - */ - function drawHalo(ctx, onMap) { - if (main.replayChecking) return; - if (!core.getLocalStorage('showHalo', true)) return; - const halo = core.status.checkBlock.halo; - ctx.save(); - for (const [loc, range] of Object.entries(halo)) { - const [x, y] = loc.split(',').map(v => parseInt(v)); - for (const r of range) { - const [type, value, color, border] = r.split(':'); - if (type === 'square') { - // 正方形光环 - const n = parseInt(value); - const r = Math.floor(n / 2); - let left = x - r, - right = x + r, - top = y - r, - bottom = y + r; - if (onMap && core.bigmap.v2) { - left -= core.bigmap.posX; - top -= core.bigmap.posY; - right -= core.bigmap.posX; - bottom -= core.bigmap.posY; - if ( - right < -1 || - left > core._PX_ / 32 + 1 || - top < -1 || - bottom > core._PY_ / 32 + 1 - ) { - continue; - } +/** + * 绘制光环范围 + * @param {CanvasRenderingContext2D} ctx + * @param {boolean} onMap + */ +export function drawHalo(ctx, onMap) { + if (main.replayChecking) return; + if (!core.getLocalStorage('showHalo', true)) return; + const halo = core.status.checkBlock.halo; + ctx.save(); + for (const [loc, range] of Object.entries(halo)) { + const [x, y] = loc.split(',').map(v => parseInt(v)); + for (const r of range) { + const [type, value, color, border] = r.split(':'); + if (type === 'square') { + // 正方形光环 + const n = parseInt(value); + const r = Math.floor(n / 2); + let left = x - r, + right = x + r, + top = y - r, + bottom = y + r; + if (onMap && core.bigmap.v2) { + left -= core.bigmap.posX; + top -= core.bigmap.posY; + right -= core.bigmap.posX; + bottom -= core.bigmap.posY; + if ( + right < -1 || + left > core._PX_ / 32 + 1 || + top < -1 || + bottom > core._PY_ / 32 + 1 + ) { + continue; } - ctx.fillStyle = color; - ctx.strokeStyle = border ?? color; - ctx.lineWidth = 1; - ctx.globalAlpha = 0.1; - ctx.fillRect(left * 32, top * 32, n * 32, n * 32); - ctx.globalAlpha = 0.6; - ctx.strokeRect(left * 32, top * 32, n * 32, n * 32); } + ctx.fillStyle = color; + ctx.strokeStyle = border ?? color; + ctx.lineWidth = 1; + ctx.globalAlpha = 0.1; + ctx.fillRect(left * 32, top * 32, n * 32, n * 32); + ctx.globalAlpha = 0.6; + ctx.strokeRect(left * 32, top * 32, n * 32, n * 32); } } - ctx.restore(); } + ctx.restore(); +} - core.plugin.halo = { - drawHalo - }; -})(); +core.plugin.halo = { + drawHalo +}; diff --git a/public/project/plugin/hero.js b/public/project/plugin/hero.js index b03fa3c..05031d9 100644 --- a/public/project/plugin/hero.js +++ b/public/project/plugin/hero.js @@ -1,87 +1,84 @@ /// -'use strict'; -(function () { - /** - * 获取勇士在某一点的属性 - * @param {keyof HeroStatus | 'all'} name - * @param {number} x - * @param {number} y - * @param {FloorIds} floorId - */ - function getHeroStatusOn(name, x, y, floorId) { - return getRealStatusOf(core.status.hero, name, x, y, floorId); +/** + * 获取勇士在某一点的属性 + * @param {keyof HeroStatus | 'all'} name + * @param {number} x + * @param {number} y + * @param {FloorIds} floorId + */ +export function getHeroStatusOn(name, x, y, floorId) { + return getHeroStatusOf(core.status.hero, name, x, y, floorId); +} + +export function getHeroStatusOf(status, name, x, y, floorId) { + return getRealStatus(status, name, x, y, floorId); +} + +function getRealStatus(status, name, x, y, floorId) { + if (name instanceof Array) { + return Object.fromEntries( + name.map(v => [ + v, + v !== 'all' && getRealStatus(status, v, x, y, floorId) + ]) + ); } - function getHeroStatusOf(status, name, x, y, floorId) { - return getRealStatus(status, name, x, y, floorId); + if (name === 'all') { + return Object.fromEntries( + Object.keys(core.status.hero).map(v => [ + v, + v !== 'all' && getRealStatus(status, v, x, y, floorId) + ]) + ); } - function getRealStatus(status, name, x, y, floorId) { - if (name instanceof Array) { - return Object.fromEntries( - name.map(v => [ - v, - v !== 'all' && getRealStatus(status, v, x, y, floorId) - ]) - ); - } - - if (name === 'all') { - return Object.fromEntries( - Object.keys(core.status.hero).map(v => [ - v, - v !== 'all' && getRealStatus(status, v, x, y, floorId) - ]) - ); - } - - let s = status?.[name] ?? core.status.hero[name]; - if (s === null || s === void 0) { - throw new ReferenceError( - `Wrong hero status property name is delivered: ${name}` - ); - } - - x ??= core.status.hero.loc.x; - y ??= core.status.hero.loc.y; - floorId ??= core.status.floorId; - - // 永夜、极昼 - if (name === 'atk' || name === 'def') { - s += window.flags?.[`night_${floorId}`] ?? 0; - } - - // 技能 - if (flags.bladeOn && flags.blade) { - const level = core.plugin.skillTree.getSkillLevel(2); - if (name === 'atk') { - s *= 1 + 0.1 * level; - } - if (name === 'def') { - s *= 1 - 0.1 * level; - } - } - if (flags.shield && flags.shieldOn) { - const level = core.plugin.skillTree.getSkillLevel(10); - if (name === 'atk') { - s *= 1 - 0.1 * level; - } - if (name === 'def') { - s *= 1 + 0.1 * level; - } - } - - // buff - if (typeof s === 'number') s *= core.getBuff(name); - - // 取整 - if (typeof s === 'number') s = Math.floor(s); - return s; + let s = status?.[name] ?? core.status.hero[name]; + if (s === null || s === void 0) { + throw new ReferenceError( + `Wrong hero status property name is delivered: ${name}` + ); } - core.plugin.hero = { - getHeroStatusOf, - getHeroStatusOn - }; -})(); + x ??= core.status.hero.loc.x; + y ??= core.status.hero.loc.y; + floorId ??= core.status.floorId; + + // 永夜、极昼 + if (name === 'atk' || name === 'def') { + s += window.flags?.[`night_${floorId}`] ?? 0; + } + + // 技能 + if (flags.bladeOn && flags.blade) { + const level = core.plugin.skillTree.getSkillLevel(2); + if (name === 'atk') { + s *= 1 + 0.1 * level; + } + if (name === 'def') { + s *= 1 - 0.1 * level; + } + } + if (flags.shield && flags.shieldOn) { + const level = core.plugin.skillTree.getSkillLevel(10); + if (name === 'atk') { + s *= 1 - 0.1 * level; + } + if (name === 'def') { + s *= 1 + 0.1 * level; + } + } + + // buff + if (typeof s === 'number') s *= core.getBuff(name); + + // 取整 + if (typeof s === 'number') s = Math.floor(s); + return s; +} + +core.plugin.hero = { + getHeroStatusOf, + getHeroStatusOn +}; diff --git a/public/project/plugin/heroFourFrames.js b/public/project/plugin/heroFourFrames.js index f12f958..d41ae38 100644 --- a/public/project/plugin/heroFourFrames.js +++ b/public/project/plugin/heroFourFrames.js @@ -1,60 +1,58 @@ /// -'use strict'; +export {}; -(function () { - ['up', 'down', 'left', 'right'].forEach(one => { - // 指定中间帧动画 - core.material.icons.hero[one].midFoot = 2; - }); +['up', 'down', 'left', 'right'].forEach(one => { + // 指定中间帧动画 + core.material.icons.hero[one].midFoot = 2; +}); - var heroMoving = timestamp => { - if (core.status.heroMoving <= 0) return; - if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) { - core.animateFrame.leftLeg++; - core.animateFrame.moveTime = timestamp; - } - core.drawHero( - ['stop', 'leftFoot', 'midFoot', 'rightFoot'][ - core.animateFrame.leftLeg % 4 - ], - 4 * core.status.heroMoving - ); - }; - core.registerAnimationFrame('heroMoving', true, heroMoving); +var heroMoving = timestamp => { + if (core.status.heroMoving <= 0) return; + if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) { + core.animateFrame.leftLeg++; + core.animateFrame.moveTime = timestamp; + } + core.drawHero( + ['stop', 'leftFoot', 'midFoot', 'rightFoot'][ + core.animateFrame.leftLeg % 4 + ], + 4 * core.status.heroMoving + ); +}; +core.registerAnimationFrame('heroMoving', true, heroMoving); - core.events._eventMoveHero_moving = function (step, moveSteps) { - var curr = moveSteps[0]; - var direction = curr[0], - x = core.getHeroLoc('x'), - y = core.getHeroLoc('y'); - // ------ 前进/后退 - var o = direction == 'backward' ? -1 : 1; - if (direction == 'forward' || direction == 'backward') - direction = core.getHeroLoc('direction'); - var faceDirection = direction; - if (direction == 'leftup' || direction == 'leftdown') - faceDirection = 'left'; - if (direction == 'rightup' || direction == 'rightdown') - faceDirection = 'right'; - core.setHeroLoc('direction', direction); - if (curr[1] <= 0) { - core.setHeroLoc('direction', faceDirection); - moveSteps.shift(); - return true; - } - if (step <= 4) core.drawHero('stop', 4 * o * step); - else if (step <= 8) core.drawHero('leftFoot', 4 * o * step); - else if (step <= 12) core.drawHero('midFoot', 4 * o * (step - 8)); - else if (step <= 16) core.drawHero('rightFoot', 4 * o * (step - 8)); // if (step == 8) { - if (step == 8 || step == 16) { - core.setHeroLoc('x', x + o * core.utils.scan2[direction].x, true); - core.setHeroLoc('y', y + o * core.utils.scan2[direction].y, true); - core.updateFollowers(); - curr[1]--; - if (curr[1] <= 0) moveSteps.shift(); - core.setHeroLoc('direction', faceDirection); - return step == 16; - } - return false; - }; -})(); +core.events._eventMoveHero_moving = function (step, moveSteps) { + var curr = moveSteps[0]; + var direction = curr[0], + x = core.getHeroLoc('x'), + y = core.getHeroLoc('y'); + // ------ 前进/后退 + var o = direction == 'backward' ? -1 : 1; + if (direction == 'forward' || direction == 'backward') + direction = core.getHeroLoc('direction'); + var faceDirection = direction; + if (direction == 'leftup' || direction == 'leftdown') + faceDirection = 'left'; + if (direction == 'rightup' || direction == 'rightdown') + faceDirection = 'right'; + core.setHeroLoc('direction', direction); + if (curr[1] <= 0) { + core.setHeroLoc('direction', faceDirection); + moveSteps.shift(); + return true; + } + if (step <= 4) core.drawHero('stop', 4 * o * step); + else if (step <= 8) core.drawHero('leftFoot', 4 * o * step); + else if (step <= 12) core.drawHero('midFoot', 4 * o * (step - 8)); + else if (step <= 16) core.drawHero('rightFoot', 4 * o * (step - 8)); // if (step == 8) { + if (step == 8 || step == 16) { + core.setHeroLoc('x', x + o * core.utils.scan2[direction].x, true); + core.setHeroLoc('y', y + o * core.utils.scan2[direction].y, true); + core.updateFollowers(); + curr[1]--; + if (curr[1] <= 0) moveSteps.shift(); + core.setHeroLoc('direction', faceDirection); + return step == 16; + } + return false; +}; diff --git a/public/project/plugin/hotReload.js b/public/project/plugin/hotReload.js index f46cb44..68cfdd8 100644 --- a/public/project/plugin/hotReload.js +++ b/public/project/plugin/hotReload.js @@ -1,5 +1,5 @@ /// -'use strict'; +export {}; (function () { if (main.mode !== 'play' || main.replayChecking) return; diff --git a/public/project/plugin/index.js b/public/project/plugin/index.js new file mode 100644 index 0000000..6aea035 --- /dev/null +++ b/public/project/plugin/index.js @@ -0,0 +1,32 @@ +import './fiveLayer'; +import './heroFourFrames'; +import './hotReload'; +import './itemDetail'; +import './popup'; +import './replay'; +import './ui'; +import * as halo from './halo'; +import * as hero from './hero'; +import * as loopMap from './loopMap'; +import * as remainEnemy from './remainEnemy'; +import * as removeMap from './removeMap'; +import * as shop from './shop'; +import * as skill from './skills'; +import * as skillTree from './skillTree'; +import * as study from './study'; +import * as towerBoss from './towerBoss'; +import * as utils from './utils'; + +export { + halo, + hero, + loopMap, + remainEnemy, + removeMap, + shop, + skill, + skillTree, + study, + towerBoss, + utils +}; diff --git a/public/project/plugin/itemDetail.js b/public/project/plugin/itemDetail.js index b15f46d..4f1e1b6 100644 --- a/public/project/plugin/itemDetail.js +++ b/public/project/plugin/itemDetail.js @@ -1,130 +1,128 @@ /// -'use strict'; +export {}; -(function () { - core.control.updateDamage = function (floorId, ctx) { - floorId = floorId || core.status.floorId; - if (!floorId || core.status.gameOver || main.mode != 'play') return; - const onMap = ctx == null; +core.control.updateDamage = function (floorId, ctx) { + floorId = floorId || core.status.floorId; + if (!floorId || core.status.gameOver || main.mode != 'play') return; + const onMap = ctx == null; - // 没有怪物手册 - if (!core.hasItem('book')) return; - core.status.damage.posX = core.bigmap.posX; - core.status.damage.posY = core.bigmap.posY; - if (!onMap) { - const width = core.floors[floorId].width, - height = core.floors[floorId].height; - // 地图过大的缩略图不绘制显伤 - if (width * height > core.bigmap.threshold) return; + // 没有怪物手册 + if (!core.hasItem('book')) return; + core.status.damage.posX = core.bigmap.posX; + core.status.damage.posY = core.bigmap.posY; + if (!onMap) { + const width = core.floors[floorId].width, + height = core.floors[floorId].height; + // 地图过大的缩略图不绘制显伤 + if (width * height > core.bigmap.threshold) return; + } + this._updateDamage_damage(floorId, onMap); + this._updateDamage_extraDamage(floorId, onMap); + getItemDetail(floorId, onMap); // 宝石血瓶详细信息 + this.drawDamage(ctx); +}; + +// 获取宝石信息 并绘制 +function getItemDetail(floorId, onMap) { + if (!core.getFlag('itemDetail')) return; + floorId ??= core.status.thisMap.floorId; + let diff = {}; + const before = core.status.hero; + const hero = core.clone(core.status.hero); + const handler = { + set(target, key, v) { + diff[key] = v - (target[key] || 0); + if (!diff[key]) diff[key] = void 0; + return true; } - this._updateDamage_damage(floorId, onMap); - this._updateDamage_extraDamage(floorId, onMap); - getItemDetail(floorId, onMap); // 宝石血瓶详细信息 - this.drawDamage(ctx); }; + core.status.hero = new Proxy(hero, handler); - // 获取宝石信息 并绘制 - function getItemDetail(floorId, onMap) { - if (!core.getFlag('itemDetail')) return; - floorId ??= core.status.thisMap.floorId; - let diff = {}; - const before = core.status.hero; - const hero = core.clone(core.status.hero); - const handler = { - set(target, key, v) { - diff[key] = v - (target[key] || 0); - if (!diff[key]) diff[key] = void 0; - return true; - } - }; - core.status.hero = new Proxy(hero, handler); - - core.status.maps[floorId].blocks.forEach(function (block) { - if (block.event.cls !== 'items' || block.disable) return; - const x = block.x, - y = block.y; - // v2优化,只绘制范围内的部分 - if (onMap && core.bigmap.v2) { - if ( - x < core.bigmap.posX - core.bigmap.extend || - x > core.bigmap.posX + core._PX_ + core.bigmap.extend || - y < core.bigmap.posY - core.bigmap.extend || - y > core.bigmap.posY + core._PY_ + core.bigmap.extend - ) { - return; - } - } - diff = {}; - const id = block.event.id; - const item = core.material.items[id]; - if (item.cls === 'equips') { - // 装备也显示 - const diff = core.clone(item.equip.value ?? {}); - const per = item.equip.percentage ?? {}; - for (const name in per) { - diff[name + 'per'] = per[name].toString() + '%'; - } - drawItemDetail(diff, x, y); + core.status.maps[floorId].blocks.forEach(function (block) { + if (block.event.cls !== 'items' || block.disable) return; + const x = block.x, + y = block.y; + // v2优化,只绘制范围内的部分 + if (onMap && core.bigmap.v2) { + if ( + x < core.bigmap.posX - core.bigmap.extend || + x > core.bigmap.posX + core._PX_ + core.bigmap.extend || + y < core.bigmap.posY - core.bigmap.extend || + y > core.bigmap.posY + core._PY_ + core.bigmap.extend + ) { return; } - // 跟数据统计原理一样 执行效果 前后比较 - core.setFlag('__statistics__', true); - try { - eval(item.itemEffect); - } catch (error) {} - drawItemDetail(diff, x, y); - }); - core.status.hero = before; - window.hero = before; - window.flags = before.flags; - } - - // 绘制 - function drawItemDetail(diff, x, y) { - const px = 32 * x + 2, - py = 32 * y + 31; - let content = ''; - // 获得数据和颜色 - let i = 0; - for (const name in diff) { - if (!diff[name]) continue; - let color = '#fff'; - - if (typeof diff[name] === 'number') - content = core.formatBigNumber(diff[name], true); - else content = diff[name]; - switch (name) { - case 'atk': - case 'atkper': - color = '#FF7A7A'; - break; - case 'def': - case 'defper': - color = '#00E6F1'; - break; - case 'mdef': - case 'mdefper': - color = '#6EFF83'; - break; - case 'hp': - color = '#A4FF00'; - break; - case 'hpmax': - case 'hpmaxper': - color = '#F9FF00'; - break; - case 'mana': - color = '#c66'; - break; - } - // 绘制 - core.status.damage.data.push({ - text: content, - px: px, - py: py - 10 * i, - color: color - }); - i++; } + diff = {}; + const id = block.event.id; + const item = core.material.items[id]; + if (item.cls === 'equips') { + // 装备也显示 + const diff = core.clone(item.equip.value ?? {}); + const per = item.equip.percentage ?? {}; + for (const name in per) { + diff[name + 'per'] = per[name].toString() + '%'; + } + drawItemDetail(diff, x, y); + return; + } + // 跟数据统计原理一样 执行效果 前后比较 + core.setFlag('__statistics__', true); + try { + eval(item.itemEffect); + } catch (error) {} + drawItemDetail(diff, x, y); + }); + core.status.hero = before; + window.hero = before; + window.flags = before.flags; +} + +// 绘制 +function drawItemDetail(diff, x, y) { + const px = 32 * x + 2, + py = 32 * y + 31; + let content = ''; + // 获得数据和颜色 + let i = 0; + for (const name in diff) { + if (!diff[name]) continue; + let color = '#fff'; + + if (typeof diff[name] === 'number') + content = core.formatBigNumber(diff[name], true); + else content = diff[name]; + switch (name) { + case 'atk': + case 'atkper': + color = '#FF7A7A'; + break; + case 'def': + case 'defper': + color = '#00E6F1'; + break; + case 'mdef': + case 'mdefper': + color = '#6EFF83'; + break; + case 'hp': + color = '#A4FF00'; + break; + case 'hpmax': + case 'hpmaxper': + color = '#F9FF00'; + break; + case 'mana': + color = '#c66'; + break; + } + // 绘制 + core.status.damage.data.push({ + text: content, + px: px, + py: py - 10 * i, + color: color + }); + i++; } -})(); +} diff --git a/public/project/plugin/loopMap.js b/public/project/plugin/loopMap.js index 8221da5..4cdef85 100644 --- a/public/project/plugin/loopMap.js +++ b/public/project/plugin/loopMap.js @@ -1,240 +1,230 @@ /// -'use strict'; +import { slide } from './utils'; -(function () { - const { slide } = core.plugin.utils; - const list = ['tower6']; +const list = ['tower6']; - /** - * 设置循环地图的偏移量 - * @param {number} offset 横向偏移量 - * @param {FloorIds} floorId - */ - function setLoopMap(offset, floorId) { - const floor = core.status.maps[floorId]; - if (offset < 9) { - moveMap(floor.width - 17, floorId); - } - if (offset > floor.width - 9) { - moveMap(17 - floor.width, floorId); +/** + * 设置循环地图的偏移量 + * @param {number} offset 横向偏移量 + * @param {FloorIds} floorId + */ +function setLoopMap(offset, floorId) { + const floor = core.status.maps[floorId]; + if (offset < 9) { + moveMap(floor.width - 17, floorId); + } + if (offset > floor.width - 9) { + moveMap(17 - floor.width, floorId); + } +} + +/** + * 当勇士移动时自动设置循环地图 + * @param {FloorIds} floorId + */ +function autoSetLoopMap(floorId) { + setLoopMap(core.status.hero.loc.x, floorId); +} + +export function checkLoopMap() { + if (isLoopMap(core.status.floorId)) { + autoSetLoopMap(core.status.floorId); + } +} + +/** + * 移动地图 + * @param {number} delta + * @param {FloorIds} floorId + */ +function moveMap(delta, floorId) { + core.extractBlocks(floorId); + const floor = core.status.maps[floorId]; + core.setHeroLoc('x', core.status.hero.loc.x + delta); + flags[`loop_${floorId}`] += delta; + flags[`loop_${floorId}`] %= floor.width; + const origin = floor.blocks.slice(); + for (let i = 0; i < origin.length; i++) { + core.removeBlockByIndex(0, floorId); + core.removeGlobalAnimate(origin[i].x, origin[i].y); + } + origin.forEach(v => { + let to = v.x + delta; + if (to >= floor.width) to -= floor.width; + if (to < 0) to += floor.width; + core.setBlock(v.id, to, v.y, floorId, true); + core.setMapBlockDisabled(floorId, to, v.y, false); + }); + core.drawMap(); + core.drawHero(); +} + +function isLoopMap(floorId) { + return list.includes(floorId); +} + +events.prototype._sys_changeFloor = function (data, callback) { + data = data.event.data; + let heroLoc = {}; + if (isLoopMap(data.floorId)) { + const floor = core.status.maps[data.floorId]; + flags[`loop_${data.floorId}`] ??= 0; + let tx = data.loc[0] + flags[`loop_${data.floorId}`]; + tx %= floor.width; + if (tx < 0) tx += floor.width; + heroLoc = { + x: tx, + y: data.loc[1] + }; + } else if (data.loc) heroLoc = { x: data.loc[0], y: data.loc[1] }; + if (data.direction) heroLoc.direction = data.direction; + if (core.status.event.id != 'action') core.status.event.id = null; + core.changeFloor(data.floorId, data.stair, heroLoc, data.time, function () { + core.replay(); + if (callback) callback(); + }); +}; + +events.prototype.trigger = function (x, y, callback) { + var _executeCallback = function () { + // 因为trigger之后还有可能触发其他同步脚本(比如阻激夹域检测) + // 所以这里强制callback被异步触发 + if (callback) { + setTimeout(callback, 1); // +1是为了录像检测系统 } + return; + }; + if (core.status.gameOver) return _executeCallback(); + if (core.status.event.id == 'action') { + core.insertAction( + { + type: 'function', + function: + 'function () { core.events._trigger_inAction(' + + x + + ',' + + y + + '); }', + async: true + }, + null, + null, + null, + true + ); + return _executeCallback(); } + if (core.status.event.id) return _executeCallback(); - /** - * 当勇士移动时自动设置循环地图 - * @param {FloorIds} floorId - */ - function autoSetLoopMap(floorId) { - setLoopMap(core.status.hero.loc.x, floorId); - } - - function checkLoopMap() { - if (isLoopMap(core.status.floorId)) { - autoSetLoopMap(core.status.floorId); - } - } - - /** - * 移动地图 - * @param {number} delta - * @param {FloorIds} floorId - */ - function moveMap(delta, floorId) { - core.extractBlocks(floorId); - const floor = core.status.maps[floorId]; - core.setHeroLoc('x', core.status.hero.loc.x + delta); - flags[`loop_${floorId}`] += delta; - flags[`loop_${floorId}`] %= floor.width; - const origin = floor.blocks.slice(); - for (let i = 0; i < origin.length; i++) { - core.removeBlockByIndex(0, floorId); - core.removeGlobalAnimate(origin[i].x, origin[i].y); - } - origin.forEach(v => { - let to = v.x + delta; - if (to >= floor.width) to -= floor.width; - if (to < 0) to += floor.width; - core.setBlock(v.id, to, v.y, floorId, true); - core.setMapBlockDisabled(floorId, to, v.y, false); - }); - core.drawMap(); - core.drawHero(); - } - - function isLoopMap(floorId) { - return list.includes(floorId); - } - - events.prototype._sys_changeFloor = function (data, callback) { - data = data.event.data; - let heroLoc = {}; - if (isLoopMap(data.floorId)) { - const floor = core.status.maps[data.floorId]; - flags[`loop_${data.floorId}`] ??= 0; - let tx = data.loc[0] + flags[`loop_${data.floorId}`]; + let block = core.getBlock(x, y); + const id = core.status.floorId; + const loop = isLoopMap(id); + if (loop && flags[`loop_${id}`] !== 0) { + if (block && block.event.trigger === 'changeFloor') { + delete block.event.trigger; + core.maps._addInfo(block); + } else { + const floor = core.status.maps[id]; + let tx = x - flags[`loop_${id}`]; tx %= floor.width; if (tx < 0) tx += floor.width; - heroLoc = { - x: tx, - y: data.loc[1] - }; - } else if (data.loc) heroLoc = { x: data.loc[0], y: data.loc[1] }; - if (data.direction) heroLoc.direction = data.direction; - if (core.status.event.id != 'action') core.status.event.id = null; - core.changeFloor( - data.floorId, - data.stair, - heroLoc, - data.time, - function () { - core.replay(); - if (callback) callback(); - } - ); - }; - - events.prototype.trigger = function (x, y, callback) { - var _executeCallback = function () { - // 因为trigger之后还有可能触发其他同步脚本(比如阻激夹域检测) - // 所以这里强制callback被异步触发 - if (callback) { - setTimeout(callback, 1); // +1是为了录像检测系统 - } - return; - }; - if (core.status.gameOver) return _executeCallback(); - if (core.status.event.id == 'action') { - core.insertAction( - { - type: 'function', - function: - 'function () { core.events._trigger_inAction(' + - x + - ',' + - y + - '); }', - async: true - }, - null, - null, - null, - true - ); - return _executeCallback(); - } - if (core.status.event.id) return _executeCallback(); - - let block = core.getBlock(x, y); - const id = core.status.floorId; - const loop = isLoopMap(id); - if (loop && flags[`loop_${id}`] !== 0) { - if (block && block.event.trigger === 'changeFloor') { - delete block.event.trigger; - core.maps._addInfo(block); - } else { - const floor = core.status.maps[id]; - let tx = x - flags[`loop_${id}`]; - tx %= floor.width; - if (tx < 0) tx += floor.width; - const c = core.floors[id].changeFloor[`${tx},${y}`]; - if (c) { - const b = { event: {}, x: tx, y }; - b.event.data = c; - b.event.trigger = 'changeFloor'; - block = b; - } + const c = core.floors[id].changeFloor[`${tx},${y}`]; + if (c) { + const b = { event: {}, x: tx, y }; + b.event.data = c; + b.event.trigger = 'changeFloor'; + block = b; } } + } - if (block == null) return _executeCallback(); + if (block == null) return _executeCallback(); - // 执行该点的脚本 - if (block.event.script) { - core.clearRouteFolding(); - try { - eval(block.event.script); - } catch (ee) { - console.error(ee); - } + // 执行该点的脚本 + if (block.event.script) { + core.clearRouteFolding(); + try { + eval(block.event.script); + } catch (ee) { + console.error(ee); } + } - // 碰触事件 - if (block.event.event) { - core.clearRouteFolding(); - core.insertAction(block.event.event, block.x, block.y); - // 不再执行该点的系统事件 - return _executeCallback(); - } - - if (block.event.trigger && block.event.trigger != 'null') { - var noPass = block.event.noPass, - trigger = block.event.trigger; - if (noPass) core.clearAutomaticRouteNode(x, y); - - // 转换楼层能否穿透 - if ( - trigger == 'changeFloor' && - !noPass && - this._trigger_ignoreChangeFloor(block) && - !loop - ) - return _executeCallback(); - core.status.automaticRoute.moveDirectly = false; - this.doSystemEvent(trigger, block); - } + // 碰触事件 + if (block.event.event) { + core.clearRouteFolding(); + core.insertAction(block.event.event, block.x, block.y); + // 不再执行该点的系统事件 return _executeCallback(); - }; + } - maps.prototype._getBgFgMapArray = function (name, floorId, noCache) { - floorId = floorId || core.status.floorId; - if (!floorId) return []; - var width = core.floors[floorId].width; - var height = core.floors[floorId].height; + if (block.event.trigger && block.event.trigger != 'null') { + var noPass = block.event.noPass, + trigger = block.event.trigger; + if (noPass) core.clearAutomaticRouteNode(x, y); - if (!noCache && core.status[name + 'maps'][floorId]) - return core.status[name + 'maps'][floorId]; + // 转换楼层能否穿透 + if ( + trigger == 'changeFloor' && + !noPass && + this._trigger_ignoreChangeFloor(block) && + !loop + ) + return _executeCallback(); + core.status.automaticRoute.moveDirectly = false; + this.doSystemEvent(trigger, block); + } + return _executeCallback(); +}; - var arr = - main.mode == 'editor' && - !(window.editor && editor.uievent && editor.uievent.isOpen) - ? core.cloneArray(editor[name + 'map']) - : null; - if (arr == null) - arr = core.cloneArray(core.floors[floorId][name + 'map'] || []); +maps.prototype._getBgFgMapArray = function (name, floorId, noCache) { + floorId = floorId || core.status.floorId; + if (!floorId) return []; + var width = core.floors[floorId].width; + var height = core.floors[floorId].height; - if (isLoopMap(floorId) && window.flags) { - flags[`loop_${floorId}`] ??= 0; - arr.forEach(v => { - slide(v, flags[`loop_${floorId}`] % width); - }); - } + if (!noCache && core.status[name + 'maps'][floorId]) + return core.status[name + 'maps'][floorId]; - for (var y = 0; y < height; ++y) { - if (arr[y] == null) arr[y] = Array(width).fill(0); - } - (core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach( - function (one) { - arr[one[1]][one[0]] = one[2] || 0; - } - ); - (core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach( - function (one) { - arr[one[1]][one[0]] = 0; - } - ); - if (main.mode == 'editor') { - for (var x = 0; x < width; x++) { - for (var y = 0; y < height; y++) { - arr[y][x] = arr[y][x].idnum || arr[y][x] || 0; - } + var arr = + main.mode == 'editor' && + !(window.editor && editor.uievent && editor.uievent.isOpen) + ? core.cloneArray(editor[name + 'map']) + : null; + if (arr == null) + arr = core.cloneArray(core.floors[floorId][name + 'map'] || []); + + if (isLoopMap(floorId) && window.flags) { + flags[`loop_${floorId}`] ??= 0; + arr.forEach(v => { + slide(v, flags[`loop_${floorId}`] % width); + }); + } + + for (var y = 0; y < height; ++y) { + if (arr[y] == null) arr[y] = Array(width).fill(0); + } + (core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(function ( + one + ) { + arr[one[1]][one[0]] = one[2] || 0; + }); + (core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(function ( + one + ) { + arr[one[1]][one[0]] = 0; + }); + if (main.mode == 'editor') { + for (var x = 0; x < width; x++) { + for (var y = 0; y < height; y++) { + arr[y][x] = arr[y][x].idnum || arr[y][x] || 0; } } - if (core.status[name + 'maps']) - core.status[name + 'maps'][floorId] = arr; - return arr; - }; + } + if (core.status[name + 'maps']) core.status[name + 'maps'][floorId] = arr; + return arr; +}; - core.plugin.loopMap = { - checkLoopMap - }; -})(); +core.plugin.loopMap = { + checkLoopMap +}; diff --git a/public/project/plugin/popup.js b/public/project/plugin/popup.js index e3d00db..0ac8994 100644 --- a/public/project/plugin/popup.js +++ b/public/project/plugin/popup.js @@ -1,124 +1,120 @@ /// -'use strict'; +export {}; -(function () { - // 伤害弹出 - // 复写阻激夹域检测 - control.prototype.checkBlock = function (forceMockery) { - var x = core.getHeroLoc('x'), - y = core.getHeroLoc('y'), - loc = x + ',' + y; - var damage = core.status.checkBlock.damage[loc]; - if (damage) { - if (!main.replayChecking) - core.addPop( - (x - core.bigmap.offsetX / 32) * 32 + 12, - (y - core.bigmap.offsetY / 32) * 32 + 20, - -damage.toString() - ); - core.status.hero.hp -= damage; - var text = - Object.keys(core.status.checkBlock.type[loc] || {}).join( - ',' - ) || '伤害'; - 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.updateStatusBar(); - core.events.lose(); - return; - } else { - core.updateStatusBar(); - } - } - this._checkBlock_repulse(core.status.checkBlock.repulse[loc]); - checkMockery(loc, forceMockery); - }; - - control.prototype.moveHero = function (direction, callback) { - // 如果正在移动,直接return - if (core.status.heroMoving != 0) return; - if (core.isset(direction)) core.setHeroLoc('direction', direction); - - const nx = core.nextX(); - const ny = core.nextY(); - if (core.status.checkBlock.mockery[`${nx},${ny}`]) { - core.autosave(); - } - - if (callback) return this.moveAction(callback); - this._moveHero_moving(); - }; - - /** - * 电摇嘲讽 - * @param {LocString} loc - * @param {boolean} force - */ - function checkMockery(loc, force) { - if (core.status.lockControl && !force) return; - const mockery = core.status.checkBlock.mockery[loc]; - if (mockery) { - mockery.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); - const action = []; - const [tx, ty] = mockery[0]; - let { x, y } = core.status.hero.loc; - const dir = - x > tx ? 'left' : x < tx ? 'right' : y > ty ? 'up' : 'down'; - const { x: dx, y: dy } = core.utils.scan[dir]; - - action.push({ type: 'changePos', direction: dir }); - const blocks = core.getMapBlocksObj(); - while (1) { - x += dx; - y += dy; - const block = blocks[`${x},${y}`]; - if (block) { - block.event.cls === ''; - if ( - [ - 'animates', - 'autotile', - 'tileset', - 'npcs', - 'npc48' - ].includes(block.event.cls) - ) { - action.push( - { - type: 'hide', - loc: [[x, y]], - remove: true, - time: 0 - }, - { - type: 'function', - function: `function() { core.removeGlobalAnimate(${x}, ${y}) }` - }, - { - type: 'animate', - name: 'hand', - loc: [x, y], - async: true - } - ); - } - if (block.event.cls.startsWith('enemy')) { - action.push({ type: 'moveAction' }); - } - } - action.push({ type: 'moveAction' }); - if (x === tx && y === ty) break; - } - action.push({ - type: 'function', - function: `function() { core.checkBlock(true); }` - }); - action.push({ type: 'stopAsync' }); - core.insertAction(action); +// 伤害弹出 +// 复写阻激夹域检测 +control.prototype.checkBlock = function (forceMockery) { + var x = core.getHeroLoc('x'), + y = core.getHeroLoc('y'), + loc = x + ',' + y; + var damage = core.status.checkBlock.damage[loc]; + if (damage) { + if (!main.replayChecking) + core.addPop( + (x - core.bigmap.offsetX / 32) * 32 + 12, + (y - core.bigmap.offsetY / 32) * 32 + 20, + -damage.toString() + ); + core.status.hero.hp -= damage; + var text = + Object.keys(core.status.checkBlock.type[loc] || {}).join(',') || + '伤害'; + 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.updateStatusBar(); + core.events.lose(); + return; + } else { + core.updateStatusBar(); } } -})(); + this._checkBlock_repulse(core.status.checkBlock.repulse[loc]); + checkMockery(loc, forceMockery); +}; + +control.prototype.moveHero = function (direction, callback) { + // 如果正在移动,直接return + if (core.status.heroMoving != 0) return; + if (core.isset(direction)) core.setHeroLoc('direction', direction); + + const nx = core.nextX(); + const ny = core.nextY(); + if (core.status.checkBlock.mockery[`${nx},${ny}`]) { + core.autosave(); + } + + if (callback) return this.moveAction(callback); + this._moveHero_moving(); +}; + +/** + * 电摇嘲讽 + * @param {LocString} loc + * @param {boolean} force + */ +function checkMockery(loc, force) { + if (core.status.lockControl && !force) return; + const mockery = core.status.checkBlock.mockery[loc]; + if (mockery) { + mockery.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + const action = []; + const [tx, ty] = mockery[0]; + let { x, y } = core.status.hero.loc; + const dir = x > tx ? 'left' : x < tx ? 'right' : y > ty ? 'up' : 'down'; + const { x: dx, y: dy } = core.utils.scan[dir]; + + action.push({ type: 'changePos', direction: dir }); + const blocks = core.getMapBlocksObj(); + while (1) { + x += dx; + y += dy; + const block = blocks[`${x},${y}`]; + if (block) { + block.event.cls === ''; + if ( + [ + 'animates', + 'autotile', + 'tileset', + 'npcs', + 'npc48' + ].includes(block.event.cls) + ) { + action.push( + { + type: 'hide', + loc: [[x, y]], + remove: true, + time: 0 + }, + { + type: 'function', + function: `function() { core.removeGlobalAnimate(${x}, ${y}) }` + }, + { + type: 'animate', + name: 'hand', + loc: [x, y], + async: true + } + ); + } + if (block.event.cls.startsWith('enemy')) { + action.push({ type: 'moveAction' }); + } + } + action.push({ type: 'moveAction' }); + if (x === tx && y === ty) break; + } + action.push({ + type: 'function', + function: `function() { core.checkBlock(true); }` + }); + action.push({ type: 'stopAsync' }); + core.insertAction(action); + } +} diff --git a/public/project/plugin/remainEnemy.js b/public/project/plugin/remainEnemy.js index e4eebc8..60afefa 100644 --- a/public/project/plugin/remainEnemy.js +++ b/public/project/plugin/remainEnemy.js @@ -1,76 +1,72 @@ /// -'use strict'; -(function () { +/** + * 检查漏怪 + * @param {FloorIds[]} floorIds + */ +export function checkRemainEnemy(floorIds) { /** - * 检查漏怪 - * @param {FloorIds[]} floorIds + * @type {Record} */ - function checkRemainEnemy(floorIds) { - /** - * @type {Record} - */ - const enemy = {}; - floorIds.forEach(v => { - core.extractBlocks(v); - const blocks = core.status.maps[v].blocks; - blocks.forEach(block => { - if (!block.event.cls.startsWith('enemy') || block.disable) - return; - /** - * @type {EnemyIds} - */ - const id = block.event.id; - enemy[v] ??= []; - const info = enemy[v]; - info.push({ loc: [block.x, block.y], id }); - }); + const enemy = {}; + floorIds.forEach(v => { + core.extractBlocks(v); + const blocks = core.status.maps[v].blocks; + blocks.forEach(block => { + if (!block.event.cls.startsWith('enemy') || block.disable) return; + /** + * @type {EnemyIds} + */ + const id = block.event.id; + enemy[v] ??= []; + const info = enemy[v]; + info.push({ loc: [block.x, block.y], id }); }); - return enemy; - } + }); + return enemy; +} - /** - * 获取剩余怪物字符串 - * @param {FloorIds[]} floorIds - */ - function getRemainEnemyString(floorIds) { - const enemy = checkRemainEnemy(floorIds); - const str = []; - let now = []; - for (const floor in enemy) { - /** - * @type {{loc: LocArr, id: EnemyIds}[]} - */ - const all = enemy[floor]; - /** - * @type {Record} - */ - const remain = {}; - all.forEach(v => { - const id = v.id; - remain[id] ??= 0; - remain[id]++; - }); - const title = core.status.maps[floor].title; - for (const id in remain) { - const name = core.material.enemys[id].name; - now.push(`${title}(${floor}): ${name} * ${remain[id]}`); - if (now.length === 10) { - str.push(now.join('\n')); - now = []; - } +/** + * 获取剩余怪物字符串 + * @param {FloorIds[]} floorIds + */ +export function getRemainEnemyString(floorIds) { + const enemy = checkRemainEnemy(floorIds); + const str = []; + let now = []; + for (const floor in enemy) { + /** + * @type {{loc: LocArr, id: EnemyIds}[]} + */ + const all = enemy[floor]; + /** + * @type {Record} + */ + const remain = {}; + all.forEach(v => { + const id = v.id; + remain[id] ??= 0; + remain[id]++; + }); + const title = core.status.maps[floor].title; + for (const id in remain) { + const name = core.material.enemys[id].name; + now.push(`${title}(${floor}): ${name} * ${remain[id]}`); + if (now.length === 10) { + str.push(now.join('\n')); + now = []; } } - if (now.length > 0) { - str.push(now.join('\n')); - str[0] = `当前剩余怪物:\n${str[0]}`; - } - - return str; + } + if (now.length > 0) { + str.push(now.join('\n')); + str[0] = `当前剩余怪物:\n${str[0]}`; } - core.plugin.remainEnemy = { - checkRemainEnemy, - getRemainEnemyString - }; -})(); + return str; +} + +core.plugin.remainEnemy = { + checkRemainEnemy, + getRemainEnemyString +}; diff --git a/public/project/plugin/removeMap.js b/public/project/plugin/removeMap.js index dc3a92f..83af608 100644 --- a/public/project/plugin/removeMap.js +++ b/public/project/plugin/removeMap.js @@ -1,118 +1,115 @@ /// -'use strict'; -(function () { - function removeMaps(fromId, toId, force) { - toId = toId || fromId; - var fromIndex = core.floorIds.indexOf(fromId), - toIndex = core.floorIds.indexOf(toId); - if (toIndex < 0) toIndex = core.floorIds.length - 1; - flags.__visited__ = flags.__visited__ || {}; - flags.__removed__ = flags.__removed__ || []; - flags.__disabled__ = flags.__disabled__ || {}; - flags.__leaveLoc__ = flags.__leaveLoc__ || {}; - flags.__forceDelete__ ??= {}; - let deleted = false; - for (var i = fromIndex; i <= toIndex; ++i) { - var floorId = core.floorIds[i]; - if (core.status.maps[floorId].deleted) continue; - delete flags.__visited__[floorId]; - flags.__removed__.push(floorId); - delete flags.__disabled__[floorId]; - delete flags.__leaveLoc__[floorId]; - (core.status.autoEvents || []).forEach(event => { - if (event.floorId == floorId && event.currentFloor) { - core.autoEventExecuting(event.symbol, false); - core.autoEventExecuted(event.symbol, false); - } - }); - core.status.maps[floorId].deleted = true; - core.status.maps[floorId].canFlyTo = false; - core.status.maps[floorId].canFlyFrom = false; - core.status.maps[floorId].cannotViewMap = true; - if (force) { - core.status.maps[floorId].forceDelete = true; - flags.__forceDelete__[floorId] = true; - } - deleteFlags(floorId); - deleted = true; - } - if (deleted && !main.replayChecking) { - core.splitArea(); - } - } - - function deleteFlags(floorId) { - delete flags[`jump_${floorId}`]; - delete flags[`inte_${floorId}`]; - delete flags[`loop_${floorId}`]; - delete flags[`melt_${floorId}`]; - delete flags[`night_${floorId}`]; - } - - // 恢复楼层 - // core.plugin.removeMap.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层 - // core.plugin.removeMap.resumeMaps("MT10") 只恢复MT10层 - function resumeMaps(fromId, toId) { - toId = toId || fromId; - var fromIndex = core.floorIds.indexOf(fromId), - toIndex = core.floorIds.indexOf(toId); - if (toIndex < 0) toIndex = core.floorIds.length - 1; - flags.__removed__ = flags.__removed__ || []; - for (var i = fromIndex; i <= toIndex; ++i) { - var floorId = core.floorIds[i]; - if (!core.status.maps[floorId].deleted) continue; - if ( - core.status.maps[floorId].forceDelete || - flags.__forceDelete__[floorId] - ) - continue; - flags.__removed__ = flags.__removed__.filter(f => { - return f != floorId; - }); - core.status.maps[floorId] = core.loadFloor(floorId); - } - } - - // 分区砍层相关 - var inAnyPartition = floorId => { - var inPartition = false; - (core.floorPartitions || []).forEach(floor => { - var fromIndex = core.floorIds.indexOf(floor[0]); - var toIndex = core.floorIds.indexOf(floor[1]); - var index = core.floorIds.indexOf(floorId); - if (fromIndex < 0 || index < 0) return; - if (toIndex < 0) toIndex = core.floorIds.length - 1; - if (index >= fromIndex && index <= toIndex) inPartition = true; - }); - return inPartition; - }; - - // 分区砍层 - function autoRemoveMaps(floorId) { - if (main.mode != 'play' || !inAnyPartition(floorId)) return; - // 根据分区信息自动砍层与恢复 - (core.floorPartitions || []).forEach(floor => { - var fromIndex = core.floorIds.indexOf(floor[0]); - var toIndex = core.floorIds.indexOf(floor[1]); - var index = core.floorIds.indexOf(floorId); - if (fromIndex < 0 || index < 0) return; - if (toIndex < 0) toIndex = core.floorIds.length - 1; - if (index >= fromIndex && index <= toIndex) { - core.plugin.removeMap.resumeMaps( - core.floorIds[fromIndex], - core.floorIds[toIndex] - ); - } else { - removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]); +export function removeMaps(fromId, toId, force) { + toId = toId || fromId; + var fromIndex = core.floorIds.indexOf(fromId), + toIndex = core.floorIds.indexOf(toId); + if (toIndex < 0) toIndex = core.floorIds.length - 1; + flags.__visited__ = flags.__visited__ || {}; + flags.__removed__ = flags.__removed__ || []; + flags.__disabled__ = flags.__disabled__ || {}; + flags.__leaveLoc__ = flags.__leaveLoc__ || {}; + flags.__forceDelete__ ??= {}; + let deleted = false; + for (var i = fromIndex; i <= toIndex; ++i) { + var floorId = core.floorIds[i]; + if (core.status.maps[floorId].deleted) continue; + delete flags.__visited__[floorId]; + flags.__removed__.push(floorId); + delete flags.__disabled__[floorId]; + delete flags.__leaveLoc__[floorId]; + (core.status.autoEvents || []).forEach(event => { + if (event.floorId == floorId && event.currentFloor) { + core.autoEventExecuting(event.symbol, false); + core.autoEventExecuted(event.symbol, false); } }); + core.status.maps[floorId].deleted = true; + core.status.maps[floorId].canFlyTo = false; + core.status.maps[floorId].canFlyFrom = false; + core.status.maps[floorId].cannotViewMap = true; + if (force) { + core.status.maps[floorId].forceDelete = true; + flags.__forceDelete__[floorId] = true; + } + deleteFlags(floorId); + deleted = true; } + if (deleted && !main.replayChecking) { + core.splitArea(); + } +} - core.plugin.removeMap = { - removeMaps, - deleteFlags, - resumeMaps, - autoRemoveMaps - }; -})(); +export function deleteFlags(floorId) { + delete flags[`jump_${floorId}`]; + delete flags[`inte_${floorId}`]; + delete flags[`loop_${floorId}`]; + delete flags[`melt_${floorId}`]; + delete flags[`night_${floorId}`]; +} + +// 恢复楼层 +// core.plugin.removeMap.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层 +// core.plugin.removeMap.resumeMaps("MT10") 只恢复MT10层 +export function resumeMaps(fromId, toId) { + toId = toId || fromId; + var fromIndex = core.floorIds.indexOf(fromId), + toIndex = core.floorIds.indexOf(toId); + if (toIndex < 0) toIndex = core.floorIds.length - 1; + flags.__removed__ = flags.__removed__ || []; + for (var i = fromIndex; i <= toIndex; ++i) { + var floorId = core.floorIds[i]; + if (!core.status.maps[floorId].deleted) continue; + if ( + core.status.maps[floorId].forceDelete || + flags.__forceDelete__[floorId] + ) + continue; + flags.__removed__ = flags.__removed__.filter(f => { + return f != floorId; + }); + core.status.maps[floorId] = core.loadFloor(floorId); + } +} + +// 分区砍层相关 +var inAnyPartition = floorId => { + var inPartition = false; + (core.floorPartitions || []).forEach(floor => { + var fromIndex = core.floorIds.indexOf(floor[0]); + var toIndex = core.floorIds.indexOf(floor[1]); + var index = core.floorIds.indexOf(floorId); + if (fromIndex < 0 || index < 0) return; + if (toIndex < 0) toIndex = core.floorIds.length - 1; + if (index >= fromIndex && index <= toIndex) inPartition = true; + }); + return inPartition; +}; + +// 分区砍层 +export function autoRemoveMaps(floorId) { + if (main.mode != 'play' || !inAnyPartition(floorId)) return; + // 根据分区信息自动砍层与恢复 + (core.floorPartitions || []).forEach(floor => { + var fromIndex = core.floorIds.indexOf(floor[0]); + var toIndex = core.floorIds.indexOf(floor[1]); + var index = core.floorIds.indexOf(floorId); + if (fromIndex < 0 || index < 0) return; + if (toIndex < 0) toIndex = core.floorIds.length - 1; + if (index >= fromIndex && index <= toIndex) { + core.plugin.removeMap.resumeMaps( + core.floorIds[fromIndex], + core.floorIds[toIndex] + ); + } else { + removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]); + } + }); +} + +core.plugin.removeMap = { + removeMaps, + deleteFlags, + resumeMaps, + autoRemoveMaps +}; diff --git a/public/project/plugin/replay.js b/public/project/plugin/replay.js index a2c6cdc..b246dd4 100644 --- a/public/project/plugin/replay.js +++ b/public/project/plugin/replay.js @@ -1,91 +1,89 @@ /// -'use strict'; -(function () { - const { studySkill, canStudySkill } = core.plugin.study; - const replayableSettings = ['autoSkill']; +import { studySkill, canStudySkill } from './study'; - // 注册修改设置的录像操作 - core.registerReplayAction('settings', name => { - if (!name.startsWith('set:')) return false; - const [, setting, value] = name.split(':'); - const v = eval(value); - if (typeof v !== 'boolean') return false; - if (!replayableSettings.includes(setting)) return false; - flags[setting] = v; - core.replay(); - return true; - }); +const replayableSettings = ['autoSkill']; - core.registerReplayAction('upgradeSkill', name => { - if (!name.startsWith('skill:')) return false; - const skill = parseInt(name.slice(6)); - core.plugin.skillTree.upgradeSkill(skill); - core.replay(); - return true; - }); +// 注册修改设置的录像操作 +core.registerReplayAction('settings', name => { + if (!name.startsWith('set:')) return false; + const [, setting, value] = name.split(':'); + const v = eval(value); + if (typeof v !== 'boolean') return false; + if (!replayableSettings.includes(setting)) return false; + flags[setting] = v; + core.replay(); + return true; +}); - core.registerReplayAction('study', name => { - if (!name.startsWith('study:')) return false; - const [num, x, y] = name - .slice(6) - .split(',') - .map(v => parseInt(v)); - if (!canStudySkill(num)) return false; - const id = core.getBlockId(x, y); - const enemy = core.getEnemyInfo(id, void 0, x, y); - if (!enemy.special.includes(num)) return false; - studySkill(enemy, num); - core.replay(); - return true; - }); +core.registerReplayAction('upgradeSkill', name => { + if (!name.startsWith('skill:')) return false; + const skill = parseInt(name.slice(6)); + core.plugin.skillTree.upgradeSkill(skill); + core.replay(); + return true; +}); - // 商店 - let shopOpened = false; - let openedShopId = ''; - core.registerReplayAction('openShop', name => { - if (!name.startsWith('openShop:')) return false; - openedShopId = name.slice(9); - shopOpened = true; - core.replay(); - return true; - }); +core.registerReplayAction('study', name => { + if (!name.startsWith('study:')) return false; + const [num, x, y] = name + .slice(6) + .split(',') + .map(v => parseInt(v)); + if (!canStudySkill(num)) return false; + const id = core.getBlockId(x, y); + const enemy = core.getEnemyInfo(id, void 0, x, y); + if (!enemy.special.includes(num)) return false; + studySkill(enemy, num); + core.replay(); + return true; +}); - core.registerReplayAction('buy', name => { - if (!name.startsWith('buy:') && !name.startsWith('sell:')) return false; - if (!shopOpened) return false; - if (!openedShopId) return false; - const [type, id, num] = name - .split(':') - .map(v => (/^\d+$/.test(v) ? parseInt(v) : v)); - const shop = core.status.shops[id]; - const item = shop.choices.find(v => v.id === id); - if (!item) return false; - flags.itemShop ??= {}; - flags.itemShop[openedShopId] ??= {}; - flags.itemShop[openedShopId][id] ??= 0; - if (num > item.number - flags.itemShop[openedShopId][id]) { - return false; - } - let cost = 0; - if (type === 'buy') { - cost = item.money * num; - } else { - cost = -item.sell * num; - } - if (cost > core.status.hero.money) return false; - core.status.hero.money -= cost; - flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num; - core.replay(); - return true; - }); +// 商店 +let shopOpened = false; +let openedShopId = ''; +core.registerReplayAction('openShop', name => { + if (!name.startsWith('openShop:')) return false; + openedShopId = name.slice(9); + shopOpened = true; + core.replay(); + return true; +}); - core.registerReplayAction('closeShop', name => { - if (name !== 'closeShop') return false; - if (!shopOpened) return false; - shopOpened = false; - openedShopId = ''; - core.replay(); - return true; - }); -})(); +core.registerReplayAction('buy', name => { + if (!name.startsWith('buy:') && !name.startsWith('sell:')) return false; + if (!shopOpened) return false; + if (!openedShopId) return false; + const [type, id, num] = name + .split(':') + .map(v => (/^\d+$/.test(v) ? parseInt(v) : v)); + const shop = core.status.shops[id]; + const item = shop.choices.find(v => v.id === id); + if (!item) return false; + flags.itemShop ??= {}; + flags.itemShop[openedShopId] ??= {}; + flags.itemShop[openedShopId][id] ??= 0; + if (num > item.number - flags.itemShop[openedShopId][id]) { + return false; + } + let cost = 0; + if (type === 'buy') { + cost = item.money * num; + } else { + cost = -item.sell * num; + } + if (cost > core.status.hero.money) return false; + core.status.hero.money -= cost; + flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num; + core.replay(); + return true; +}); + +core.registerReplayAction('closeShop', name => { + if (name !== 'closeShop') return false; + if (!shopOpened) return false; + shopOpened = false; + openedShopId = ''; + core.replay(); + return true; +}); diff --git a/public/project/plugin/shop.js b/public/project/plugin/shop.js index 1495351..9dff3c6 100644 --- a/public/project/plugin/shop.js +++ b/public/project/plugin/shop.js @@ -1,77 +1,74 @@ /// -'use strict'; -(function () { - const { openItemShop } = core.plugin.gameUi; +const { openItemShop } = core.plugin.gameUi; - function openShop(shopId, noRoute) { - var shop = core.status.shops[shopId]; - // Step 1: 检查能否打开此商店 - if (!this.canOpenShop(shopId)) { - core.drawTip('该商店尚未开启'); - return false; - } - - // Step 3: 检查道具商店 or 公共事件 - if (shop.item) { - if (openItemShop) openItemShop(shopId); - return; - } - return true; +export function openShop(shopId, noRoute) { + var shop = core.status.shops[shopId]; + // Step 1: 检查能否打开此商店 + if (!this.canOpenShop(shopId)) { + core.drawTip('该商店尚未开启'); + return false; } - /// 是否访问过某个快捷商店 - function isShopVisited(id) { - flags.__shops__ ??= {}; - var shops = core.getFlag('__shops__'); - if (!shops[id]) shops[id] = {}; - return shops[id].visited; + // Step 3: 检查道具商店 or 公共事件 + if (shop.item) { + if (openItemShop) openItemShop(shopId); + return; } + return true; +} - /// 当前应当显示的快捷商店列表 - function listShopIds() { - return Object.keys(core.status.shops).filter(id => { - return ( - core.plugin.shop.isShopVisited(id) || - !core.status.shops[id].mustEnable - ); - }); - } +/// 是否访问过某个快捷商店 +export function isShopVisited(id) { + flags.__shops__ ??= {}; + var shops = core.getFlag('__shops__'); + if (!shops[id]) shops[id] = {}; + return shops[id].visited; +} - /// 是否能够打开某个商店 - function canOpenShop(id) { - if (this.isShopVisited(id)) return true; - var shop = core.status.shops[id]; - if (shop.item || shop.commonEvent || shop.mustEnable) return false; - return true; - } +/// 当前应当显示的快捷商店列表 +export function listShopIds() { + return Object.keys(core.status.shops).filter(id => { + return ( + core.plugin.shop.isShopVisited(id) || + !core.status.shops[id].mustEnable + ); + }); +} - /// 启用或禁用某个快捷商店 - function setShopVisited(id, visited) { - if (!core.hasFlag('__shops__')) core.setFlag('__shops__', {}); - var shops = core.getFlag('__shops__'); - if (!shops[id]) shops[id] = {}; - if (visited) shops[id].visited = true; - else delete shops[id].visited; - } +/// 是否能够打开某个商店 +export function canOpenShop(id) { + if (this.isShopVisited(id)) return true; + var shop = core.status.shops[id]; + if (shop.item || shop.commonEvent || shop.mustEnable) return false; + return true; +} - /// 能否使用快捷商店 - function canUseQuickShop() { - // 如果返回一个字符串,表示不能,字符串为不能使用的提示 - // 返回null代表可以使用 +/// 启用或禁用某个快捷商店 +export function setShopVisited(id, visited) { + if (!core.hasFlag('__shops__')) core.setFlag('__shops__', {}); + var shops = core.getFlag('__shops__'); + if (!shops[id]) shops[id] = {}; + if (visited) shops[id].visited = true; + else delete shops[id].visited; +} - // 检查当前楼层的canUseQuickShop选项是否为false - if (core.status.thisMap.canUseQuickShop === false) - return '当前楼层不能使用快捷商店。'; - return null; - } +/// 能否使用快捷商店 +export function canUseQuickShop() { + // 如果返回一个字符串,表示不能,字符串为不能使用的提示 + // 返回null代表可以使用 - core.plugin.shop = { - openShop, - isShopVisited, - listShopIds, - canOpenShop, - setShopVisited, - canUseQuickShop - }; -})(); + // 检查当前楼层的canUseQuickShop选项是否为false + if (core.status.thisMap.canUseQuickShop === false) + return '当前楼层不能使用快捷商店。'; + return null; +} + +core.plugin.shop = { + openShop, + isShopVisited, + listShopIds, + canOpenShop, + setShopVisited, + canUseQuickShop +}; diff --git a/public/project/plugin/skillTree.js b/public/project/plugin/skillTree.js index b273450..a5fe565 100644 --- a/public/project/plugin/skillTree.js +++ b/public/project/plugin/skillTree.js @@ -1,320 +1,316 @@ /// -'use strict'; -(function () { - /** - * @type {number[]} - */ - let levels = []; +/** + * @type {number[]} + */ +let levels = []; - /** - * @type {Record} - */ - const skills = { - chapter1: [ - { - index: 0, - title: '力量', - desc: ['力量就是根本!可以通过智慧增加力量,每级增加2点攻击。'], - consume: '10 * level + 10', - front: [], - loc: [1, 2], - max: 10, - effect: ['攻击 + ${level * 2}'] - }, - { - index: 1, - title: '致命一击', - desc: ['爆发出全部力量攻击敌人,每级增加5点额外攻击。'], - consume: '30 * level + 30', - front: [[0, 5]], - loc: [2, 1], - max: 10, - effect: ['额外攻击 + ${level * 5}'] - }, - { - index: 2, - title: '断灭之刃', - desc: [ - '主动技能,快捷键1,', - '开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。' - ], - consume: '200 * level + 400', - front: [[1, 5]], - loc: [4, 1], - max: 5, - effect: ['增加${level * 10}%攻击,减少${level * 10}%防御'] - }, - { - index: 3, - title: '坚韧', - desc: ['由智慧转化出坚韧!每级增加2点防御'], - consume: '10 * level + 10', - front: [], - loc: [1, 4], - max: 10, - effect: ['防御 + ${level * 2}'] - }, - { - index: 4, - title: '回春', - desc: ['让智慧化为治愈之泉水!每级增加1点生命回复'], - consume: '20 * level + 20', - front: [[3, 5]], - loc: [2, 5], - max: 25, - effect: ['生命回复 + ${level}'] - }, - { - index: 5, - title: '治愈之泉', - desc: [ - '让生命变得更多一些吧!每吃50瓶血瓶就增加当前生命回复10%的生命回复' - ], - consume: '1500', - front: [[4, 25]], - loc: [4, 5], - max: 1, - effect: ['50瓶血10%生命回复'] - }, - { - index: 6, - title: '坚固之盾', - desc: ['让护甲更加坚硬一些吧!每级增加10点防御'], - consume: '50 + level * 50', - front: [[3, 5]], - loc: [2, 3], - max: 10, - effect: ['防御 + ${level * 10}'] - }, - { - index: 7, - title: '无上之盾', - desc: [ - '第一章终极技能,战斗时智慧会充当等量护盾' - ], - consume: '2500', - front: [ - [6, 10], - [5, 1], - [2, 2] - ], - loc: [5, 3], - max: 1, - effect: ['战斗时智慧会充当护盾'] +/** + * @type {Record} + */ +const skills = { + chapter1: [ + { + index: 0, + title: '力量', + desc: ['力量就是根本!可以通过智慧增加力量,每级增加2点攻击。'], + consume: '10 * level + 10', + front: [], + loc: [1, 2], + max: 10, + effect: ['攻击 + ${level * 2}'] + }, + { + index: 1, + title: '致命一击', + desc: ['爆发出全部力量攻击敌人,每级增加5点额外攻击。'], + consume: '30 * level + 30', + front: [[0, 5]], + loc: [2, 1], + max: 10, + effect: ['额外攻击 + ${level * 5}'] + }, + { + index: 2, + title: '断灭之刃', + desc: [ + '主动技能,快捷键1,', + '开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。' + ], + consume: '200 * level + 400', + front: [[1, 5]], + loc: [4, 1], + max: 5, + effect: ['增加${level * 10}%攻击,减少${level * 10}%防御'] + }, + { + index: 3, + title: '坚韧', + desc: ['由智慧转化出坚韧!每级增加2点防御'], + consume: '10 * level + 10', + front: [], + loc: [1, 4], + max: 10, + effect: ['防御 + ${level * 2}'] + }, + { + index: 4, + title: '回春', + desc: ['让智慧化为治愈之泉水!每级增加1点生命回复'], + consume: '20 * level + 20', + front: [[3, 5]], + loc: [2, 5], + max: 25, + effect: ['生命回复 + ${level}'] + }, + { + index: 5, + title: '治愈之泉', + desc: [ + '让生命变得更多一些吧!每吃50瓶血瓶就增加当前生命回复10%的生命回复' + ], + consume: '1500', + front: [[4, 25]], + loc: [4, 5], + max: 1, + effect: ['50瓶血10%生命回复'] + }, + { + index: 6, + title: '坚固之盾', + desc: ['让护甲更加坚硬一些吧!每级增加10点防御'], + consume: '50 + level * 50', + front: [[3, 5]], + loc: [2, 3], + max: 10, + effect: ['防御 + ${level * 10}'] + }, + { + index: 7, + title: '无上之盾', + desc: [ + '第一章终极技能,战斗时智慧会充当等量护盾' + ], + consume: '2500', + front: [ + [6, 10], + [5, 1], + [2, 2] + ], + loc: [5, 3], + max: 1, + effect: ['战斗时智慧会充当护盾'] + } + ], + chapter2: [ + { + index: 8, + title: '锋利', + desc: ['让剑变得更加锋利!每级使攻击增加1%(buff式增加)'], + consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250', + front: [], + loc: [1, 2], + max: 15, + effect: ['攻击增加${level}%'] + }, + { + index: 9, + title: '坚硬', + desc: ['让盾牌变得更加坚固!每级使防御增加1%(buff式增加)'], + consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250', + front: [], + loc: [1, 4], + max: 15, + effect: ['防御增加${level}%'] + }, + { + index: 10, + title: '铸剑为盾', + desc: [ + '主动技能,快捷键3,', + '减少一定的攻击,增加一定的防御' + ], + consume: '500 * level + 1000', + front: [[9, 5]], + loc: [2, 5], + max: 5, + effect: ['增加${level * 10}%的防御,减少${level * 10}%的攻击'] + }, + { + index: 11, + title: '学习', + desc: [ + '主动技能,可以消耗500智慧学习一个怪物的技能,', + '持续5场战斗,每学习一次消耗的智慧点增加250,每次升级使持续的战斗次数增加3次。更多信息可在学习后在百科全书查看。' + ], + consume: '2500 * level ** 2 + 2500', + front: [ + [8, 10], + [12, 5] + ], + loc: [4, 1], + max: 6, + effect: ['学习怪物技能,持续${level * 3 + 2}场战斗'] + }, + { + index: 12, + title: '聪慧', + desc: ['使主角变得更加聪明,每级使绿宝石增加的智慧点上升5%'], + consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250', + front: [ + [8, 10], + [9, 10] + ], + loc: [3, 3], + max: 20, + effect: ['增加${level * 5}%绿宝石效果'] + }, + { + index: 13, + title: '治愈', + desc: ['使主角能够更好地回复生命,每级使血瓶的加血量增加2%'], + consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250', + front: [[10, 3]], + loc: [4, 5], + max: 20, + effect: ['增加${level * 2}%的血瓶回血量'] + }, + { + index: 14, + title: '胜利之号', + desc: [ + '第二章终极技能,', + '每打一个怪物,勇士在本楼层对怪物造成的伤害便增加1%' + ], + consume: '15000', + front: [ + [13, 10], + [12, 10], + [11, 3] + ], + loc: [5, 3], + max: 1, + effect: ['每打一个怪,勇士造成的伤害增加1%'] + } + ] +}; + +core.plugin.skills = skills; + +export function getSkillFromIndex(index) { + for (const [, skill] of Object.entries(skills)) { + const s = skill.find(v => v.index === index); + if (s) return s; + } +} + +/** + * 获取技能等级 + * @param {number} skill + */ +export function getSkillLevel(skill) { + return (levels[skill] ??= 0); +} + +export function getSkillConsume(skill) { + return eval( + this.getSkillFromIndex(skill).consume.replace( + /level(:\d+)?/g, + (str, $1) => { + if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`; + else return `core.plugin.skillTree.getSkillLevel(${skill})`; } - ], - chapter2: [ - { - index: 8, - title: '锋利', - desc: ['让剑变得更加锋利!每级使攻击增加1%(buff式增加)'], - consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250', - front: [], - loc: [1, 2], - max: 15, - effect: ['攻击增加${level}%'] - }, - { - index: 9, - title: '坚硬', - desc: ['让盾牌变得更加坚固!每级使防御增加1%(buff式增加)'], - consume: 'level > 5 ? 50 * level ** 2 : 250 * level + 250', - front: [], - loc: [1, 4], - max: 15, - effect: ['防御增加${level}%'] - }, - { - index: 10, - title: '铸剑为盾', - desc: [ - '主动技能,快捷键3,', - '减少一定的攻击,增加一定的防御' - ], - consume: '500 * level + 1000', - front: [[9, 5]], - loc: [2, 5], - max: 5, - effect: ['增加${level * 10}%的防御,减少${level * 10}%的攻击'] - }, - { - index: 11, - title: '学习', - desc: [ - '主动技能,可以消耗500智慧学习一个怪物的技能,', - '持续5场战斗,每学习一次消耗的智慧点增加250,每次升级使持续的战斗次数增加3次。更多信息可在学习后在百科全书查看。' - ], - consume: '2500 * level ** 2 + 2500', - front: [ - [8, 10], - [12, 5] - ], - loc: [4, 1], - max: 6, - effect: ['学习怪物技能,持续${level * 3 + 2}场战斗'] - }, - { - index: 12, - title: '聪慧', - desc: ['使主角变得更加聪明,每级使绿宝石增加的智慧点上升5%'], - consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250', - front: [ - [8, 10], - [9, 10] - ], - loc: [3, 3], - max: 20, - effect: ['增加${level * 5}%绿宝石效果'] - }, - { - index: 13, - title: '治愈', - desc: ['使主角能够更好地回复生命,每级使血瓶的加血量增加2%'], - consume: 'level > 5 ? 100 * level ** 2 : 250 * level + 1250', - front: [[10, 3]], - loc: [4, 5], - max: 20, - effect: ['增加${level * 2}%的血瓶回血量'] - }, - { - index: 14, - title: '胜利之号', - desc: [ - '第二章终极技能,', - '每打一个怪物,勇士在本楼层对怪物造成的伤害便增加1%' - ], - consume: '15000', - front: [ - [13, 10], - [12, 10], - [11, 3] - ], - loc: [5, 3], - max: 1, - effect: ['每打一个怪,勇士造成的伤害增加1%'] - } - ] - }; + ) + ); +} - core.plugin.skills = skills; +export function openTree() { + if (main.replayChecking) return; + core.plugin.skillTreeOpened.value = true; +} - function getSkillFromIndex(index) { - for (const [, skill] of Object.entries(skills)) { - const s = skill.find(v => v.index === index); - if (s) return s; - } +/** + * 能否升级某个技能 + * @param {number} skill + */ +export function canUpgrade(skill) { + const consume = core.plugin.skillTree.getSkillConsume(skill); + if (consume > core.status.hero.mdef) return false; + const level = core.plugin.skillTree.getSkillLevel(skill); + const s = getSkillFromIndex(skill); + if (level === s.max) return false; + const front = s.front; + for (const [skill, level] of front) { + if (core.plugin.skillTree.getSkillLevel(skill) < level) return false; } + return true; +} - /** - * 获取技能等级 - * @param {number} skill - */ - function getSkillLevel(skill) { - return (levels[skill] ??= 0); +/** + * 实际升级效果 + * @param {number} skill + */ +export function upgradeSkill(skill) { + if (!canUpgrade(skill)) return false; + switch (skill) { + case 0: // 力量 +2攻击 + core.status.hero.atk += 2; + break; + case 1: // 致命一击 +5额外攻击 + core.status.hero.mana += 5; + break; + case 2: // 断灭之刃 + core.setFlag('bladeOn', true); + break; + case 3: // 坚韧 +2防御 + core.status.hero.def += 2; + break; + case 4: // 回春 +1回复 + core.status.hero.hpmax += 1; + break; + case 5: // 治愈之泉 + core.setFlag('spring', true); + break; + case 6: // 坚固之盾 +10防御 + core.status.hero.def += 10; + break; + case 7: // 无上之盾 + core.setFlag('superSheild', true); + break; + case 8: // 锋利 +1%攻击 + core.addBuff('atk', 0.01); + break; + case 9: // 锋利 +1%防御 + core.addBuff('def', 0.01); + break; + case 10: // 铸剑为盾 + core.setFlag('shieldOn', true); + break; + case 11: // 学习 + core.setItem('I565', 1); + break; } + const consume = getSkillConsume(skill); + core.status.hero.mdef -= consume; + levels[skill]++; + core.updateStatusBar(); + return true; +} - function getSkillConsume(skill) { - return eval( - this.getSkillFromIndex(skill).consume.replace( - /level(:\d+)?/g, - (str, $1) => { - if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`; - else return `core.plugin.skillTree.getSkillLevel(${skill})`; - } - ) - ); - } +export function saveSkillTree() { + return levels.slice(); +} - function openTree() { - if (main.replayChecking) return; - core.plugin.skillTreeOpened.value = true; - } +export function loadSkillTree(data) { + levels = data ?? []; +} - /** - * 能否升级某个技能 - * @param {number} skill - */ - function canUpgrade(skill) { - const consume = core.plugin.skillTree.getSkillConsume(skill); - if (consume > core.status.hero.mdef) return false; - const level = core.plugin.skillTree.getSkillLevel(skill); - const s = getSkillFromIndex(skill); - if (level === s.max) return false; - const front = s.front; - for (const [skill, level] of front) { - if (core.plugin.skillTree.getSkillLevel(skill) < level) - return false; - } - return true; - } - - /** - * 实际升级效果 - * @param {number} skill - */ - function upgradeSkill(skill) { - if (!canUpgrade(skill)) return false; - switch (skill) { - case 0: // 力量 +2攻击 - core.status.hero.atk += 2; - break; - case 1: // 致命一击 +5额外攻击 - core.status.hero.mana += 5; - break; - case 2: // 断灭之刃 - core.setFlag('bladeOn', true); - break; - case 3: // 坚韧 +2防御 - core.status.hero.def += 2; - break; - case 4: // 回春 +1回复 - core.status.hero.hpmax += 1; - break; - case 5: // 治愈之泉 - core.setFlag('spring', true); - break; - case 6: // 坚固之盾 +10防御 - core.status.hero.def += 10; - break; - case 7: // 无上之盾 - core.setFlag('superSheild', true); - break; - case 8: // 锋利 +1%攻击 - core.addBuff('atk', 0.01); - break; - case 9: // 锋利 +1%防御 - core.addBuff('def', 0.01); - break; - case 10: // 铸剑为盾 - core.setFlag('shieldOn', true); - break; - case 11: // 学习 - core.setItem('I565', 1); - break; - } - const consume = getSkillConsume(skill); - core.status.hero.mdef -= consume; - levels[skill]++; - core.updateStatusBar(); - return true; - } - - function saveSkillTree() { - return levels.slice(); - } - - function loadSkillTree(data) { - levels = data ?? []; - } - - core.plugin.skillTree = { - getSkillConsume, - getSkillFromIndex, - getSkillLevel, - saveSkillTree, - loadSkillTree, - upgradeSkill, - openTree - }; -})(); +core.plugin.skillTree = { + getSkillConsume, + getSkillFromIndex, + getSkillLevel, + saveSkillTree, + loadSkillTree, + upgradeSkill, + openTree +}; diff --git a/public/project/plugin/skills.js b/public/project/plugin/skills.js index cc2e337..d0352bd 100644 --- a/public/project/plugin/skills.js +++ b/public/project/plugin/skills.js @@ -1,182 +1,173 @@ /// -'use strict'; -(function () { - // 所有的主动技能效果 - var ignoreInJump = { - event: ['X20007', 'X20001', 'X20006', 'X20014', 'X20010', 'X20007'], - bg: [ - 'X20037', - 'X20038', - 'X20039', - 'X20045', - 'X20047', - 'X20053', - 'X20054', - 'X20055', - 'X20067', - 'X20068', - 'X20075', - 'X20076' - ] - }; +// 所有的主动技能效果 +var ignoreInJump = { + event: ['X20007', 'X20001', 'X20006', 'X20014', 'X20010', 'X20007'], + bg: [ + 'X20037', + 'X20038', + 'X20039', + 'X20045', + 'X20047', + 'X20053', + 'X20054', + 'X20055', + 'X20067', + 'X20068', + 'X20075', + 'X20076' + ] +}; - /** @type {FloorIds[]} */ - const jumpIgnoreFloor = ['MT31', 'snowTown']; - // 跳跃 - function jumpSkill() { - if (core.status.floorId.startsWith('tower')) - return core.drawTip('当无法使用该技能'); - if (jumpIgnoreFloor.includes(core.status.floorId) || flags.onChase) { - return core.drawTip('当前楼层无法使用该技能'); - } - if (!flags.skill2) return; - if (!flags['jump_' + core.status.floorId]) - flags['jump_' + core.status.floorId] = 0; +/** @type {FloorIds[]} */ +const jumpIgnoreFloor = ['MT31', 'snowTown']; +// 跳跃 +export function jumpSkill() { + if (core.status.floorId.startsWith('tower')) + return core.drawTip('当无法使用该技能'); + if (jumpIgnoreFloor.includes(core.status.floorId) || flags.onChase) { + return core.drawTip('当前楼层无法使用该技能'); + } + if (!flags.skill2) return; + if (!flags['jump_' + core.status.floorId]) + flags['jump_' + core.status.floorId] = 0; + if ( + core.status.floorId == 'MT14' && + flags['jump_' + core.status.floorId] == 2 && + !flags.MT14Jump + ) { if ( - core.status.floorId == 'MT14' && - flags['jump_' + core.status.floorId] == 2 && - !flags.MT14Jump + !( + core.status.hero.loc.x === 77 && + core.status.hero.loc.y === 5 && + core.status.hero.loc.direction === 'right' + ) ) { - if ( - !( - core.status.hero.loc.x === 77 && - core.status.hero.loc.y === 5 && - core.status.hero.loc.direction === 'right' - ) - ) { - return core.drawTip('该地图还有一个必跳的地方,你还没有跳'); - } else flags.MT14Jump = true; + return core.drawTip('该地图还有一个必跳的地方,你还没有跳'); + } else flags.MT14Jump = true; + } + if (flags['jump_' + core.status.floorId] >= 3) + return core.drawTip('当前地图使用次数已用完'); + var direction = core.status.hero.loc.direction; + var loc = core.status.hero.loc; + var checkLoc = {}; + switch (direction) { + case 'up': + checkLoc.x = loc.x; + checkLoc.y = loc.y - 1; + break; + case 'right': + checkLoc.x = loc.x + 1; + checkLoc.y = loc.y; + break; + case 'down': + checkLoc.x = loc.x; + checkLoc.y = loc.y + 1; + break; + case 'left': + checkLoc.x = loc.x - 1; + checkLoc.y = loc.y; + break; + } + // 前方是否可通行 或 是怪物 + var cls = core.getBlockCls(checkLoc.x, checkLoc.y); + var noPass = core.noPass(checkLoc.x, checkLoc.y); + var id = core.getBlockId(checkLoc.x, checkLoc.y) || ''; + var bgId = + core.getBlockByNumber(core.getBgNumber(checkLoc.x, checkLoc.y)).event + .id || ''; + // 可以通行 + if ( + !noPass || + cls == 'items' || + (id.startsWith('X') && !ignoreInJump.event.includes(id)) || + (bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId)) + ) + return core.drawTip('当前无法使用技能'); + // 不是怪物且不可以通行 + if (noPass && !(cls == 'enemys' || cls == 'enemy48')) { + var toLoc = checkNoPass(direction, checkLoc.x, checkLoc.y, true); + if (!toLoc) return; + core.autosave(); + if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard; + core.updateStatusBar(); + flags['jump_' + core.status.floorId]++; + if (core.status.hero.hp <= 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose('你跳死了'); } - if (flags['jump_' + core.status.floorId] >= 3) - return core.drawTip('当前地图使用次数已用完'); - var direction = core.status.hero.loc.direction; - var loc = core.status.hero.loc; - var checkLoc = {}; + core.playSound('015-Jump01.ogg'); + core.insertAction([ + { type: 'jumpHero', loc: [toLoc.x, toLoc.y], time: 500 } + ]); + } + // 是怪物 + if (cls == 'enemys' || cls == 'enemy48') { + var firstNoPass = checkNoPass(direction, checkLoc.x, checkLoc.y, false); + if (!firstNoPass) return; + core.autosave(); + if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard; + core.updateStatusBar(); + flags['jump_' + core.status.floorId]++; + if (core.status.hero.hp <= 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose('你跳死了'); + } + core.playSound('015-Jump01.ogg'); + core.insertAction([ + { + type: 'jump', + from: [checkLoc.x, checkLoc.y], + to: [firstNoPass.x, firstNoPass.y], + time: 500, + keep: true + } + ]); + } + // 检查一条线上的不可通过 + function checkNoPass(direction, x, y, startNo) { + if (!startNo) startNo = false; switch (direction) { case 'up': - checkLoc.x = loc.x; - checkLoc.y = loc.y - 1; + y--; break; case 'right': - checkLoc.x = loc.x + 1; - checkLoc.y = loc.y; + x++; break; case 'down': - checkLoc.x = loc.x; - checkLoc.y = loc.y + 1; + y++; break; case 'left': - checkLoc.x = loc.x - 1; - checkLoc.y = loc.y; + x--; break; } - // 前方是否可通行 或 是怪物 - var cls = core.getBlockCls(checkLoc.x, checkLoc.y); - var noPass = core.noPass(checkLoc.x, checkLoc.y); - var id = core.getBlockId(checkLoc.x, checkLoc.y) || ''; - var bgId = - core.getBlockByNumber(core.getBgNumber(checkLoc.x, checkLoc.y)) - .event.id || ''; - // 可以通行 if ( - !noPass || - cls == 'items' || - (id.startsWith('X') && !ignoreInJump.event.includes(id)) || - (bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId)) + x > core.status.thisMap.width - 1 || + y > core.status.thisMap.height - 1 || + x < 0 || + y < 0 ) return core.drawTip('当前无法使用技能'); - // 不是怪物且不可以通行 - if (noPass && !(cls == 'enemys' || cls == 'enemy48')) { - var toLoc = checkNoPass(direction, checkLoc.x, checkLoc.y, true); - if (!toLoc) return; - core.autosave(); - if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard; - core.updateStatusBar(); - flags['jump_' + core.status.floorId]++; - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose('你跳死了'); - } - core.playSound('015-Jump01.ogg'); - core.insertAction([ - { type: 'jumpHero', loc: [toLoc.x, toLoc.y], time: 500 } - ]); - } - // 是怪物 - if (cls == 'enemys' || cls == 'enemy48') { - var firstNoPass = checkNoPass( - direction, - checkLoc.x, - checkLoc.y, - false - ); - if (!firstNoPass) return; - core.autosave(); - if (flags.chapter <= 1) core.status.hero.hp -= 200 * flags.hard; - core.updateStatusBar(); - flags['jump_' + core.status.floorId]++; - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose('你跳死了'); - } - core.playSound('015-Jump01.ogg'); - core.insertAction([ - { - type: 'jump', - from: [checkLoc.x, checkLoc.y], - to: [firstNoPass.x, firstNoPass.y], - time: 500, - keep: true - } - ]); - } - // 检查一条线上的不可通过 - function checkNoPass(direction, x, y, startNo) { - if (!startNo) startNo = false; - switch (direction) { - case 'up': - y--; - break; - case 'right': - x++; - break; - case 'down': - y++; - break; - case 'left': - x--; - break; - } - if ( - x > core.status.thisMap.width - 1 || - y > core.status.thisMap.height - 1 || - x < 0 || - y < 0 - ) - return core.drawTip('当前无法使用技能'); - var id = core.getBlockId(x, y) || ''; - if (core.getBgNumber(x, y)) - var bgId = - core.getBlockByNumber(core.getBgNumber(x, y)).event.id || - ''; - else var bgId = ''; - if ( - core.noPass(x, y) || - core.getBlockCls(x, y) == 'items' || - (id.startsWith('X') && !ignoreInJump.event.includes(id)) || - (bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId)) || - core.getBlockCls(x, y) == 'animates' - ) - return checkNoPass(direction, x, y, true); - if (!startNo) return checkNoPass(direction, x, y, false); - return { x: x, y: y }; - } + var id = core.getBlockId(x, y) || ''; + if (core.getBgNumber(x, y)) + var bgId = + core.getBlockByNumber(core.getBgNumber(x, y)).event.id || ''; + else var bgId = ''; + if ( + core.noPass(x, y) || + core.getBlockCls(x, y) == 'items' || + (id.startsWith('X') && !ignoreInJump.event.includes(id)) || + (bgId.startsWith('X') && !ignoreInJump.bg.includes(bgId)) || + core.getBlockCls(x, y) == 'animates' + ) + return checkNoPass(direction, x, y, true); + if (!startNo) return checkNoPass(direction, x, y, false); + return { x: x, y: y }; } +} - core.plugin.skillEffects = { - jumpSkill - }; -})(); +core.plugin.skillEffects = { + jumpSkill +}; diff --git a/public/project/plugin/study.js b/public/project/plugin/study.js index a090ce2..f7471ec 100644 --- a/public/project/plugin/study.js +++ b/public/project/plugin/study.js @@ -1,80 +1,77 @@ /// -'use strict'; -(function () { - // 负责勇士技能:学习 - const values = { - 1: ['crit'], - 6: ['n'], - 7: ['hungry'], - 8: ['together'], - 10: ['courage'], - 11: ['charge'] - }; +// 负责勇士技能:学习 +const values = { + 1: ['crit'], + 6: ['n'], + 7: ['hungry'], + 8: ['together'], + 10: ['courage'], + 11: ['charge'] +}; - const cannotStudy = [9, 12, 14, 15, 24]; +const cannotStudy = [9, 12, 14, 15, 24]; - function canStudySkill(number) { - const s = (core.status.hero.special ??= { num: [], last: [] }); - if (core.plugin.skillTree.getSkillLevel(11) === 0) return false; - if (s.num.length >= 1) return false; - if (s.num.includes(number)) return false; - if (cannotStudy.includes(number)) return false; - return true; - } +export function canStudySkill(number) { + const s = (core.status.hero.special ??= { num: [], last: [] }); + if (core.plugin.skillTree.getSkillLevel(11) === 0) return false; + if (s.num.length >= 1) return false; + if (s.num.includes(number)) return false; + if (cannotStudy.includes(number)) return false; + return true; +} - function studySkill(enemy, number) { - core.status.hero.special ??= { num: [], last: [] }; - const s = core.status.hero.special; - const specials = core.getSpecials(); - let special = specials[number - 1][1]; - if (special instanceof Function) special = special(enemy); - if (!canStudySkill(number)) { - if (!main.replayChecking) { - core.tip('error', `无法学习${special}`); - } - return; +export function studySkill(enemy, number) { + core.status.hero.special ??= { num: [], last: [] }; + const s = core.status.hero.special; + const specials = core.getSpecials(); + let special = specials[number - 1][1]; + if (special instanceof Function) special = special(enemy); + if (!canStudySkill(number)) { + if (!main.replayChecking) { + core.tip('error', `无法学习${special}`); } - s.num.push(number); - s.last.push(core.plugin.skillTree.getSkillLevel(11) * 3 + 2); - const value = values[number] ?? []; - for (const key of value) { - s[key] = enemy[key]; + return; + } + s.num.push(number); + s.last.push(core.plugin.skillTree.getSkillLevel(11) * 3 + 2); + const value = values[number] ?? []; + for (const key of value) { + s[key] = enemy[key]; + } +} + +export function forgetStudiedSkill(num, i) { + const s = core.status.hero.special; + const index = i !== void 0 && i !== null ? i : s.num.indexOf(num); + if (index === -1) return; + s.num.splice(index, 1); + s.last.splice(index, 1); + const value = values[number] ?? []; + for (const key of value) { + delete s[key]; + } +} + +export function declineStudiedSkill() { + const s = (core.status.hero.special ??= { num: [], last: [] }); + s.last = s.last.map(v => v - 1); +} + +export function checkStudiedSkill() { + const s = core.status.hero.special; + for (let i = 0; i < s.last.length; i++) { + if (s.last[i] <= 0) { + this.forgetStudiedSkill(void 0, i); + i--; } } +} - function forgetStudiedSkill(num, i) { - const s = core.status.hero.special; - const index = i !== void 0 && i !== null ? i : s.num.indexOf(num); - if (index === -1) return; - s.num.splice(index, 1); - s.last.splice(index, 1); - const value = values[number] ?? []; - for (const key of value) { - delete s[key]; - } - } - - function declineStudiedSkill() { - const s = (core.status.hero.special ??= { num: [], last: [] }); - s.last = s.last.map(v => v - 1); - } - - function checkStudiedSkill() { - const s = core.status.hero.special; - for (let i = 0; i < s.last.length; i++) { - if (s.last[i] <= 0) { - this.forgetStudiedSkill(void 0, i); - i--; - } - } - } - - core.plugin.study = { - canStudySkill, - studySkill, - forgetStudiedSkill, - declineStudiedSkill, - checkStudiedSkill - }; -})(); +core.plugin.study = { + canStudySkill, + studySkill, + forgetStudiedSkill, + declineStudiedSkill, + checkStudiedSkill +}; diff --git a/public/project/plugin/towerBoss.js b/public/project/plugin/towerBoss.js index a2e8231..353dbeb 100644 --- a/public/project/plugin/towerBoss.js +++ b/public/project/plugin/towerBoss.js @@ -1,168 +1,182 @@ /// -'use strict'; -// 1000多行,改不动了 +// 1000多行,改不动了,原来什么样就什么样吧 -(function () { - // 智慧boss - // 变量们 - var stage = 1, - hp = 10000, - seconds = 0, - boomLocs = [], // 随机轰炸 - heroHp; - // 初始化 - function initTowerBoss() { - stage = 1; - hp = 10000; - seconds = 0; - heroHp = core.status.hero.hp; - dynamicChangeHp(0, 10000, 10000); - autoFixRouteBoss(true); - core.insertAction([{ type: 'sleep', time: 1000, noSkip: true }]); - setTimeout(bossCore, 1000); +// 智慧boss +// 变量们 +var stage = 1, + hp = 10000, + seconds = 0, + boomLocs = [], // 随机轰炸 + heroHp; +// 初始化 +function initTowerBoss() { + stage = 1; + hp = 10000; + seconds = 0; + heroHp = core.status.hero.hp; + dynamicChangeHp(0, 10000, 10000); + autoFixRouteBoss(true); + core.insertAction([{ type: 'sleep', time: 1000, noSkip: true }]); + setTimeout(bossCore, 1000); +} +// 录像自动修正 +export function autoFixRouteBoss(isStart) { + var route = core.status.route; + if (isStart) { + // 开始修正 记录当前录像长度 + flags.startFix = route.length - 1; + return; } - // 录像自动修正 - function autoFixRouteBoss(isStart) { - var route = core.status.route; - if (isStart) { - // 开始修正 记录当前录像长度 - flags.startFix = route.length - 1; + // 结束修正 删除录像 并追加跳过步骤 + route.splice(flags.startFix); + route.push('choices:0'); + delete flags.startFix; +} +// 血条 +function healthBar(now, total) { + var nowLength = (now / total) * 476; // 当前血量下绘制长度 + var color = [ + 255 * 2 - (now / total) * 2 * 255, + (now / total) * 2 * 255, + 0, + 1 + ]; // 根据当前血量计算颜色 + // 建画布 + if (!core.dymCanvas.healthBar) + core.createCanvas('healthBar', 0, 0, 480, 16, 140); + else core.clearMap('healthBar'); + // 底 + core.fillRect('healthBar', 0, 0, 480, 16, '#bbbbbb'); + // css特效 + var style = document.getElementById('healthBar').getContext('2d'); + style.shadowColor = 'rgba(0, 0, 0, 0.8)'; + style.shadowBlur = 5; + style.shadowOffsetX = 10; + style.shadowOffsetY = 5; + style.filter = 'blur(1px)'; + // 绘制 + core.fillRect('healthBar', 2, 2, nowLength, 12, color); + // css特效 + style.shadowColor = 'rgba(0, 0, 0, 0.5)'; + style.shadowOffsetX = 0; + style.shadowOffsetY = 0; + // 绘制边框 + core.strokeRect('healthBar', 1, 1, 478, 14, '#ffffff', 2); + // 绘制文字 + style.shadowColor = 'rgba(0, 0, 0, 1)'; + style.shadowBlur = 3; + style.shadowOffsetX = 2; + style.shadowOffsetY = 1; + style.filter = 'none'; + core.fillText( + 'healthBar', + now + '/' + total, + 5, + 13.5, + '#ffffff', + '16px normal' + ); +} +// 血量变化 +function dynamicChangeHp(from, to, total) { + var frame = 0, + speed = (to - from) / 50, + now = from; + var interval = window.setInterval(() => { + frame++; + if (frame == 50) { + clearInterval(interval); + healthBar(to, total); + } + now += speed; + healthBar(now, total); + }, 20); +} +// boss说话跳字 +function skipWord(words, x, y, time) { + x = x || 0; + y = y || 16; + time = time || 3000; + // 创建画布 + if (!core.dymCanvas.words) core.createCanvas('words', x, y, 480, 24, 135); + else core.clearMap('words'); + if (flags.wordsTimeOut) clearTimeout(flags.wordsTimeOut); + dynamicCurtain(y, y + 24, time / 3); + // css + var style = document.getElementById('words').getContext('2d'); + style.shadowColor = 'rgba(0, 0, 0, 1)'; + style.shadowBlur = 3; + style.shadowOffsetX = 2; + style.shadowOffsetY = 1; + // 一个一个绘制 + skip1(0); + // 跳字 + function skip1(now) { + if (parseInt(now) >= words.length) { + flags.wordsTimeOut = setTimeout(() => { + core.deleteCanvas('words'); + core.deleteCanvas('wordsBg'); + }, time); return; } - // 结束修正 删除录像 并追加跳过步骤 - route.splice(flags.startFix); - route.push('choices:0'); - delete flags.startFix; - } - // 血条 - function healthBar(now, total) { - var nowLength = (now / total) * 476; // 当前血量下绘制长度 - var color = [ - 255 * 2 - (now / total) * 2 * 255, - (now / total) * 2 * 255, - 0, - 1 - ]; // 根据当前血量计算颜色 - // 建画布 - if (!core.dymCanvas.healthBar) - core.createCanvas('healthBar', 0, 0, 480, 16, 140); - else core.clearMap('healthBar'); - // 底 - core.fillRect('healthBar', 0, 0, 480, 16, '#bbbbbb'); - // css特效 - var style = document.getElementById('healthBar').getContext('2d'); - style.shadowColor = 'rgba(0, 0, 0, 0.8)'; - style.shadowBlur = 5; - style.shadowOffsetX = 10; - style.shadowOffsetY = 5; - style.filter = 'blur(1px)'; - // 绘制 - core.fillRect('healthBar', 2, 2, nowLength, 12, color); - // css特效 - style.shadowColor = 'rgba(0, 0, 0, 0.5)'; - style.shadowOffsetX = 0; - style.shadowOffsetY = 0; - // 绘制边框 - core.strokeRect('healthBar', 1, 1, 478, 14, '#ffffff', 2); - // 绘制文字 - style.shadowColor = 'rgba(0, 0, 0, 1)'; - style.shadowBlur = 3; - style.shadowOffsetX = 2; - style.shadowOffsetY = 1; - style.filter = 'none'; - core.fillText( - 'healthBar', - now + '/' + total, - 5, - 13.5, - '#ffffff', - '16px normal' - ); - } - // 血量变化 - function dynamicChangeHp(from, to, total) { var frame = 0, - speed = (to - from) / 50, - now = from; - var interval = window.setInterval(() => { + blur = 2, + nx = 4 + now * 24; + var skip2 = window.setInterval(() => { + blur -= 0.4; frame++; - if (frame == 50) { - clearInterval(interval); - healthBar(to, total); + core.clearMap('words', nx, 0, 24, 24); + style.filter = 'blur(' + blur + 'px)'; + core.fillText( + 'words', + words[now], + nx, + 20, + '#ffffff', + '22px normal' + ); + if (frame == 5) { + clearInterval(skip2); + skip1(now + 1); } - now += speed; - healthBar(now, total); }, 20); } - // boss说话跳字 - function skipWord(words, x, y, time) { - x = x || 0; - y = y || 16; - time = time || 3000; - // 创建画布 - if (!core.dymCanvas.words) - core.createCanvas('words', x, y, 480, 24, 135); - else core.clearMap('words'); - if (flags.wordsTimeOut) clearTimeout(flags.wordsTimeOut); - dynamicCurtain(y, y + 24, time / 3); - // css - var style = document.getElementById('words').getContext('2d'); - style.shadowColor = 'rgba(0, 0, 0, 1)'; +} +// 匀变速下降背景 +function dynamicCurtain(from, to, time, width) { + width = width || 480; + if (!core.dymCanvas.wordsBg) + core.createCanvas('wordsBg', 0, from, width, 24, 130); + else core.clearMap('wordsBg'); + time /= 1000; + var ny = from, + frame = 0, + a = (2 * (to - from)) / Math.pow(time * 50, 2), + speed = a * time * 50; + var style = document.getElementById('wordsBg').getContext('2d'); + style.shadowColor = 'rgba(0, 0, 0, 0.8)'; + var wordsInterval = window.setInterval(() => { + frame++; + speed -= a; + ny += speed; + core.clearMap('wordsBg'); + style.shadowBlur = 8; + style.shadowOffsetY = 2; + core.fillRect('wordsBg', 0, 0, width, ny - from, [180, 180, 180, 0.7]); style.shadowBlur = 3; - style.shadowOffsetX = 2; - style.shadowOffsetY = 1; - // 一个一个绘制 - skip1(0); - // 跳字 - function skip1(now) { - if (parseInt(now) >= words.length) { - flags.wordsTimeOut = setTimeout(() => { - core.deleteCanvas('words'); - core.deleteCanvas('wordsBg'); - }, time); - return; - } - var frame = 0, - blur = 2, - nx = 4 + now * 24; - var skip2 = window.setInterval(() => { - blur -= 0.4; - frame++; - core.clearMap('words', nx, 0, 24, 24); - style.filter = 'blur(' + blur + 'px)'; - core.fillText( - 'words', - words[now], - nx, - 20, - '#ffffff', - '22px normal' - ); - if (frame == 5) { - clearInterval(skip2); - skip1(now + 1); - } - }, 20); - } - } - // 匀变速下降背景 - function dynamicCurtain(from, to, time, width) { - width = width || 480; - if (!core.dymCanvas.wordsBg) - core.createCanvas('wordsBg', 0, from, width, 24, 130); - else core.clearMap('wordsBg'); - time /= 1000; - var ny = from, - frame = 0, - a = (2 * (to - from)) / Math.pow(time * 50, 2), - speed = a * time * 50; - var style = document.getElementById('wordsBg').getContext('2d'); - style.shadowColor = 'rgba(0, 0, 0, 0.8)'; - var wordsInterval = window.setInterval(() => { - frame++; - speed -= a; - ny += speed; + style.shadowOffsetY = 0; + core.strokeRect( + 'wordsBg', + 1, + 1, + width - 2, + ny - from - 2, + [255, 255, 255, 0.7], + 2 + ); + if (frame >= time * 50) { + clearInterval(wordsInterval); core.clearMap('wordsBg'); style.shadowBlur = 8; style.shadowOffsetY = 2; @@ -171,7 +185,7 @@ 0, 0, width, - ny - from, + to - from, [180, 180, 180, 0.7] ); style.shadowBlur = 3; @@ -185,74 +199,69 @@ [255, 255, 255, 0.7], 2 ); - if (frame >= time * 50) { - clearInterval(wordsInterval); - core.clearMap('wordsBg'); - style.shadowBlur = 8; - style.shadowOffsetY = 2; - core.fillRect( - 'wordsBg', - 0, - 0, - width, - to - from, - [180, 180, 180, 0.7] - ); - style.shadowBlur = 3; - style.shadowOffsetY = 0; - core.strokeRect( - 'wordsBg', - 1, - 1, - width - 2, - ny - from - 2, - [255, 255, 255, 0.7], - 2 - ); - } - }, 20); - } - // 攻击boss - function attackBoss() { - // 每秒钟地面随机出现伤害图块 踩上去攻击boss 500血 - if (flags.canAttack) return; - if (Math.random() < 0.8) return; - if (hp > 3500) { - var nx = Math.floor(Math.random() * 13 + 1), - ny = Math.floor(Math.random() * 13 + 1); - } else if (hp > 2000) { - var nx = Math.floor(Math.random() * 11 + 2), - ny = Math.floor(Math.random() * 11 + 2); - } else if (hp > 1000) { - var nx = Math.floor(Math.random() * 9 + 3), - ny = Math.floor(Math.random() * 9 + 3); - } else { - var nx = Math.floor(Math.random() * 7 + 4), - ny = Math.floor(Math.random() * 7 + 4); } - // 在地图上显示 - flags.canAttack = true; - if (!core.dymCanvas.attackBoss) - core.createCanvas('attackBoss', 0, 0, 480, 480, 35); - else core.clearMap('attackBoss'); - var style = document.getElementById('attackBoss').getContext('2d'); - var frame1 = 0, - blur = 3, - scale = 2, - speed = 0.04, - a = 0.0008; - var atkAnimate = window.setInterval(() => { - core.clearMap('attackBoss'); - frame1++; - speed -= a; - scale -= speed; - blur -= 0.06; - style.filter = 'blur(' + blur + 'px)'; + }, 20); +} +// 攻击boss +function attackBoss() { + // 每秒钟地面随机出现伤害图块 踩上去攻击boss 500血 + if (flags.canAttack) return; + if (Math.random() < 0.8) return; + if (hp > 3500) { + var nx = Math.floor(Math.random() * 13 + 1), + ny = Math.floor(Math.random() * 13 + 1); + } else if (hp > 2000) { + var nx = Math.floor(Math.random() * 11 + 2), + ny = Math.floor(Math.random() * 11 + 2); + } else if (hp > 1000) { + var nx = Math.floor(Math.random() * 9 + 3), + ny = Math.floor(Math.random() * 9 + 3); + } else { + var nx = Math.floor(Math.random() * 7 + 4), + ny = Math.floor(Math.random() * 7 + 4); + } + // 在地图上显示 + flags.canAttack = true; + if (!core.dymCanvas.attackBoss) + core.createCanvas('attackBoss', 0, 0, 480, 480, 35); + else core.clearMap('attackBoss'); + var style = document.getElementById('attackBoss').getContext('2d'); + var frame1 = 0, + blur = 3, + scale = 2, + speed = 0.04, + a = 0.0008; + var atkAnimate = window.setInterval(() => { + core.clearMap('attackBoss'); + frame1++; + speed -= a; + scale -= speed; + blur -= 0.06; + style.filter = 'blur(' + blur + 'px)'; + core.strokeCircle( + 'attackBoss', + nx * 32 + 16, + ny * 32 + 16, + 16 * scale, + [255, 150, 150, 0.7], + 4 + ); + core.fillCircle( + 'attackBoss', + nx * 32 + 16, + ny * 32 + 16, + 3 * scale, + [255, 150, 150, 0.7] + ); + if (frame1 == 50) { + clearInterval(atkAnimate); + core.clearMap('attactkBoss'); + style.filter = 'none'; core.strokeCircle( 'attackBoss', nx * 32 + 16, ny * 32 + 16, - 16 * scale, + 16, [255, 150, 150, 0.7], 4 ); @@ -260,1399 +269,1306 @@ 'attackBoss', nx * 32 + 16, ny * 32 + 16, - 3 * scale, + 3, [255, 150, 150, 0.7] ); - if (frame1 == 50) { - clearInterval(atkAnimate); - core.clearMap('attactkBoss'); - style.filter = 'none'; - core.strokeCircle( - 'attackBoss', - nx * 32 + 16, - ny * 32 + 16, - 16, - [255, 150, 150, 0.7], - 4 - ); - core.fillCircle( - 'attackBoss', - nx * 32 + 16, - ny * 32 + 16, - 3, - [255, 150, 150, 0.7] - ); - } - }, 20); - // 实时检测勇士位置 - var frame2 = 0; - var atkBoss = window.setInterval(() => { - frame2++; - var x = core.status.hero.loc.x, - y = core.status.hero.loc.y; - // 2秒超时 - if (frame2 > 100) { - setTimeout(() => { - delete flags.canAttack; - }, 4000); - clearInterval(atkBoss); - core.deleteCanvas('attackBoss'); - return; - } - if (nx == x && ny == y) { - setTimeout(() => { - delete flags.canAttack; - }, 4000); - dynamicChangeHp(hp, hp - 500, 10000); - hp -= 500; - clearInterval(atkBoss); - core.deleteCanvas('attackBoss'); - if (hp > 3500) core.drawAnimate('hand', 7, 1); - else if (hp > 2000) core.drawAnimate('hand', 7, 2); - else if (hp > 1000) core.drawAnimate('hand', 7, 3); - else core.drawAnimate('hand', 7, 4); - return; - } - }, 20); - } - // 核心函数 - function bossCore() { - var interval = window.setInterval(() => { - if (stage == 1) { - if (seconds == 8) skipWord('智慧之神:果然,你和别人不一样。'); - if (seconds == 12) skipWord('智慧之神:你知道去躲避那些攻击。'); - if (seconds == 16) - skipWord( - '智慧之神:之前的那些人总会一头撞上我的攻击,悲剧收场。' - ); - if (seconds == 20) - skipWord('提示:踩在红圈上可以对智慧之神造成伤害'); - if (seconds > 10) attackBoss(); - if (seconds % 10 == 0) intelligentArrow(); - if (seconds % 7 == 0 && seconds != 0) intelligentDoor(); - if (seconds > 20 && seconds % 13 == 0) icyMomentem(); - } - if (stage == 1 && hp <= 7000) { - stage++; - seconds = 0; - skipWord('智慧之神:不错小伙子'); - core.pauseBgm(); - } - if (stage == 2) { - if (seconds == 4) skipWord('智慧之神:你的确拥有智慧。'); - if (seconds == 8) - skipWord('智慧之神:或许你就是那个未来的救星。'); - if (seconds == 12) - skipWord('智慧之神:不过,这场战斗才刚刚开始'); - if (seconds == 25) skipWord('提示:方形区域均为危险区域'); - if (seconds == 15) - setTimeout(() => { - core.playSound('thunder.mp3'); - }, 500); - if (seconds == 16) startStage2(); - if (seconds > 20) attackBoss(); - if (seconds % 4 == 0 && seconds > 20) randomThunder(); - if (seconds > 30 && seconds % 12 == 0) ballThunder(); - } - if (hp <= 3500 && stage == 2) { - stage++; - seconds = 0; - skipWord('智慧之神:不得不说小伙子'); - core.pauseBgm(); - } - if (stage >= 3) { - if (seconds == 4) skipWord('智慧之神:拥有智慧就是不一样。'); - if (seconds == 8) - skipWord('智慧之神:不过,你还得再过我一关!'); - if (seconds == 12) startStage3(); - if (seconds == 15) { - flags.booming = true; - randomBoom(); - } - if (seconds > 20) attackBoss(); - if (seconds > 20 && seconds % 10 == 0) chainThunder(); - if (hp == 2000 && stage == 3) { - stage++; - flags.booming = false; - skipWord('智慧之神:还没有结束!'); - startStage4(); - setTimeout(() => { - flags.booming = true; - randomBoom(); - }, 5000); - } - if (hp == 1000 && stage == 4) { - stage++; - flags.booming = false; - skipWord('智慧之神:还没有结束!!!!!!'); - startStage5(); - setTimeout(() => { - flags.booming = true; - randomBoom(); - }, 5000); - } - } - if (hp == 0) { - clearInterval(interval); - clearInterval(flags.boom); - core.status.hero.hp = heroHp; - core.plugin.towerBoss.autoFixRouteBoss(false); - delete flags.__bgm__; - core.pauseBgm(); - core.insertAction([ - '\t[智慧之神,E557]\b[down,7,4]看来你真的会成为那个拯救未来的人。', - '\t[智慧之神,E557]\b[down,7,4]记住,拥有智慧便可以掌控万物。', - '\t[低级智人]\b[up,hero]智慧?智慧到底是什么?', - '\t[智慧之神,E557]\b[down,7,4]最终,你会知道答案的。', - '\t[智慧之神,E557]\b[down,7,4]继续向东前进吧,那里能找到你想要的答案。', - { type: 'openDoor', loc: [13, 6], floorId: 'MT19' }, - '\t[智慧之神,E557]\b[down,7,4]我这就把你送出去', - { type: 'setValue', name: 'flag:boss1', value: 'true' }, - { type: 'changeFloor', floorId: 'MT20', loc: [7, 9] }, - { type: 'forbidSave' }, - { type: 'showStatusBar' }, - { - type: 'function', - function: '() => {\ncore.deleteAllCanvas();\n}' - } - ]); - } - seconds++; - }, 1000); - } - // ------ 第一阶段 10000~7000血 ------ // - // 技能1 智慧之箭 1000伤害 - function intelligentArrow(fromSelf) { - // 坐标 - var loc = Math.floor(Math.random() * 13 + 1); - var direction = Math.random() > 0.5 ? 'horizon' : 'vertical'; - // 执行次数 - if (!fromSelf) { - var times = Math.ceil(Math.random() * 8) + 4; - var nowTime = 1; - var times1 = window.setInterval(() => { - intelligentArrow(true); - nowTime++; - if (nowTime >= times) { - clearInterval(times1); - } - }, 200); } - // 防重复 - if (core.dymCanvas['inteArrow' + loc + direction]) - return intelligentArrow(true); - // 危险区域 - if (!core.dymCanvas.danger1) - core.createCanvas('danger1', 0, 0, 480, 480, 35); - if (direction == 'horizon') { - for (var nx = 1; nx < 14; nx++) { - core.fillRect( - 'danger1', - nx * 32 + 2, - loc * 32 + 2, - 28, - 28, - [255, 0, 0, 0.6] - ); - } - } else { - for (var ny = 1; ny < 14; ny++) { - core.fillRect( - 'danger1', - loc * 32 + 2, - ny * 32 + 2, - 28, - 28, - [255, 0, 0, 0.6] - ); - } - } - // 箭 - if (!core.dymCanvas['inteArrow' + loc + direction]) - core.createCanvas( - 'inteArrow' + loc + direction, - 0, - 0, - 544, - 544, - 65 - ); - core.clearMap('inteArrow' + loc + direction); - if (direction == 'horizon') - core.drawImage( - 'inteArrow' + loc + direction, - 'arrow.png', - 448, - loc * 32, - 102, - 32 - ); - else - core.drawImage( - 'inteArrow' + loc + direction, - 'arrow.png', - 0, - 0, - 259, - 75, - loc * 32 - 32, - 480, - 102, - 32, - Math.PI / 2 - ); - // 动画与伤害函数 - setTimeout(() => { - core.playSound('arrow.mp3'); - core.deleteCanvas('danger1'); - // 动画效果 - var nloc = 0, - speed = 0; - var damaged = {}; - var skill1 = window.setInterval(() => { - speed -= 1; - nloc += speed; - if (direction == 'horizon') - core.relocateCanvas('inteArrow' + loc + direction, nloc, 0); - else - core.relocateCanvas('inteArrow' + loc + direction, 0, nloc); - if (nloc < -480) { - core.deleteCanvas('inteArrow' + loc + direction); - clearInterval(skill1); - } - // 伤害判定 - if (!damaged[loc + direction]) { - var x = core.status.hero.loc.x, - y = core.status.hero.loc.y; - if (direction == 'horizon') { - if (y == loc && Math.floor((480 + nloc) / 32) == x) { - damaged[loc + direction] = true; - core.drawHeroAnimate('hand'); - core.status.hero.hp -= 1000; - core.addPop(x * 32 + 16, y * 32 + 16, -1000); - core.updateStatusBar(); - if (core.status.hero.hp < 0) { - clearInterval(skill1); - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - return; - } - } - } else { - if (x == loc && Math.floor((480 + nloc) / 32) == y) { - damaged[loc + direction] = true; - core.drawHeroAnimate('hand'); - core.status.hero.hp -= 1000; - core.addPop(x * 32 + 16, y * 32 + 16, -1000); - core.updateStatusBar(); - if (core.status.hero.hp < 0) { - clearInterval(skill1); - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - return; - } - } - } - } - }, 20); - }, 3000); - } - // 技能2 智慧之门 随机传送 - function intelligentDoor() { - if (Math.random() < 0.5) return; - // 随机位置 - var toX = Math.floor(Math.random() * 13) + 1, - toY = Math.floor(Math.random() * 13) + 1; - // 在勇士身上绘制动画 - core.drawHeroAnimate('magicAtk'); - // 在目标位置绘制动画 - if (!core.dymCanvas['door' + toX + '_' + toY]) - core.createCanvas('door' + toX + '_' + toY, 0, 0, 480, 480, 35); - else core.clearMap('door' + toX + '_' + toY); - var style = document - .getElementById('door' + toX + '_' + toY) - .getContext('2d'); - var frame = 0, - width = 0, - a = 0.0128, - speed = 0.64; - // 动画 - var skill2 = window.setInterval(() => { - frame++; - if (frame < 40) return; - if (frame == 100) { - clearInterval(skill2); - // 执行传送 - core.insertAction([{ type: 'changePos', loc: [toX, toY] }]); - // 删除传送门 - setTimeout(() => { - core.deleteCanvas('door' + toX + '_' + toY); - }, 2000); - return; - } - width += speed * 2; - speed -= a; - core.clearMap('door' + toX + '_' + toY); - style.shadowColor = 'rgba(255, 255, 255, 1)'; - style.shadowBlur = 7; - style.filter = 'blur(5px)'; - core.fillRect( - 'door' + toX + '_' + toY, - toX * 32, - toY * 32 - 24, - width, - 48, - [255, 255, 255, 0.7] - ); - style.shadowColor = 'rgba(0, 0, 0, 0.5)'; - style.filter = 'blur(3px)'; - core.strokeRect( - 'door' + toX + '_' + toY, - toX * 32, - toY * 32 - 24, - width, - 48, - [255, 255, 255, 0.7], - 3 - ); - }, 20); - } - // 技能3 万冰之势 全屏随机转换滑冰 如果转换时在滑冰上造成5000点伤害 - function icyMomentem() { - if (flags.haveIce) return; - if (Math.random() < 0.5) return; - var times = Math.floor(Math.random() * 100); - // 防卡 就setInterval吧 - var locs = [], - now = 0; - flags.haveIce = true; - if (!core.dymCanvas.icyMomentem) - core.createCanvas('icyMomentem', 0, 0, 480, 480, 35); - else core.clearMap('icyMomentem'); - var skill3 = window.setInterval(() => { - var nx = Math.floor(Math.random() * 13) + 1, - ny = Math.floor(Math.random() * 13) + 1; - if (!locs.includes([nx, ny])) { - locs.push([nx, ny]); - core.fillRect( - 'icyMomentem', - locs[now][0] * 32 + 2, - locs[now][1] * 32 + 2, - 28, - 28, - [150, 150, 255, 0.6] - ); - } - if (now == times) { - clearInterval(skill3); - skill3Effect(); - } - now++; - }, 20); - // 动画和伤害函数 - function skill3Effect() { - // 防卡 setInterval - var index = 0; - var effect = window.setInterval(() => { - var x = core.status.hero.loc.x, - y = core.status.hero.loc.y; - core.clearMap( - 'icyMomentem', - locs[index][0] * 32, - locs[index][1] * 32, - 32, - 32 - ); - core.setBgFgBlock('bg', 167, locs[index][0], locs[index][1]); - core.drawAnimate('ice', locs[index][0], locs[index][1]); - if (x == locs[index][0] && y == locs[index][1]) { - core.drawHeroAnimate('hand'); - core.status.hero.hp -= 5000; - core.addPop(x * 32 + 16, y * 32 + 16, -5000); - core.updateStatusBar(); - if (core.status.hero.hp < 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - clearInterval(effect); - return; - } - } - if (index >= locs.length - 1) { - clearInterval(effect); - setTimeout(() => { - deleteIce(locs); - }, 5000); - } - index++; - }, 50); - } - // 删除函数 - function deleteIce(locs) { - // 照样 setInterval - var index = 0; - var deleteIce = window.setInterval(() => { - core.setBgFgBlock('bg', 0, locs[index][0], locs[index][1]); - index++; - if (index >= locs.length) { - clearInterval(deleteIce); - core.deleteCanvas('icyMomentem'); - setTimeout(() => { - delete flags.haveIce; - }, 5000); - } - }, 50); - } - } - // ------ 第二阶段 7000~3500 ------ // - // 开始第二阶段 - function startStage2() { - // 闪烁 - core.createCanvas('flash', 0, 0, 480, 480, 160); - var alpha = 0; - var frame = 0; - var start1 = window.setInterval(() => { - core.clearMap('flash'); - frame++; - if (frame <= 8) alpha += 0.125; - else alpha -= 0.01; - core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); - if (alpha == 0) { - clearInterval(start1); - core.deleteCanvas('flash'); - } - if (frame == 8) { - changeWeather(); - } - }); - // 切换天气 - function changeWeather() { - core.setWeather(); - core.setWeather('rain', 10); - core.setWeather('fog', 8); - // 色调也得换 - core.setCurtain([0, 0, 0, 0.3]); - // bgm - core.playBgm('towerBoss2.mp3'); - } - } - // ----- 打雷相关 ----- // - // 随机打雷 - function randomThunder() { - var x = Math.floor(Math.random() * 13) + 1, - y = Math.floor(Math.random() * 13) + 1, - power = Math.ceil(Math.random() * 6); - // 绘制危险区域 - if (!core.dymCanvas.thunderDanger) - core.createCanvas('thunderDanger', 0, 0, 480, 480, 35); - else core.clearMap('thunderDanger'); - // 3*3范围 - for (var nx = x - 1; nx <= x + 1; nx++) { - for (var ny = y - 1; ny <= y + 1; ny++) { - core.fillRect( - 'thunderDanger', - nx * 32 + 2, - ny * 32 + 2, - 28, - 28, - [255, 255, 255, 0.6] - ); - } - } - core.deleteCanvas('flash'); - setTimeout(() => { - core.playSound('thunder.mp3'); - }, 500); - setTimeout(() => { - core.deleteCanvas('thunderDanger'); - drawThunder(x, y, power); - }, 1000); - } - // 绘制 - function drawThunder(x, y, power) { - var route = getThunderRoute(x * 32 + 16, y * 32 + 16, power); - // 开始绘制 - if (!core.dymCanvas.thunder) - core.createCanvas('thunder', 0, 0, 480, 480, 65); - else core.clearMap('thunder'); - var style = core.dymCanvas.thunder; - style.shadowColor = 'rgba(220, 220, 255, 1)'; - style.shadowBlur = power; - style.filter = 'blur(2.5px)'; - for (var num in route) { - // 一个个绘制 - for (var i = 0; i < route[num].length - 1; i++) { - var now = route[num][i], - next = route[num][i + 1]; - core.drawLine( - 'thunder', - now[0], - now[1], - next[0], - next[1], - '#ffffff', - 2.5 - ); - } - } - // 伤害 - getThunderRoute(x, y, power); - // 闪一下 - var frame1 = 0, - alpha = 0.5; - if (!core.dymCanvas.flash) - core.createCanvas('flash', 0, 0, 480, 480, 160); - else core.clearMap('flash'); - var thunderFlash = window.setInterval(() => { - alpha -= 0.05; - frame1++; - core.clearMap('flash'); - core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); - if (frame1 >= 10) { - clearInterval(thunderFlash); - core.deleteCanvas('flash'); - // 删除闪电 - setTimeout(() => { - core.deleteCanvas('thunder'); - }, 700); - } - }, 20); - } - // 获得雷电路径 - function getThunderRoute(x, y, power) { - var route = []; - for (var num = 0; num < power; num++) { - var nx = x, - ny = y; - route[num] = []; - for (var i = 0; ny >= 0; i++) { - if (i > 0) { - nx += Math.random() * 30 - 15; - ny -= Math.random() * 80 + 30; - } else { - nx += Math.random() * 16 - 8; - ny += Math.random() * 16 - 8; - } - route[num].push([nx, ny]); - } - } - return route; - } - // 打雷伤害判定 - function getThunderDamage(x, y, power) { - var hx = core.status.hero.loc.x, - hy = core.status.hero.loc.y; - if (Math.abs(hx - x) <= 1 && Math.abs(hy - y) <= 1) { - core.status.hero.hp -= 3000 * power; - core.addPop(x * 32 + 16, y * 32 + 16, -3000 * power); - core.updateStatusBar(); - if (core.status.hero.hp < 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - return; - } - } - } - // ----- 打雷 END ----- // - // 球形闪电 横竖 - function ballThunder() { - // 随机数量 - var times = Math.ceil(Math.random() * 12) + 6; - var now = 0, - locs = []; - // setInterval执行 - var ballThunder = window.setInterval(() => { - // 画布 - if (!core.dymCanvas['ballThunder' + now]) - core.createCanvas('ballThunder' + now, 0, 0, 480, 480, 35); - else core.clearMap('ballThunder' + now); - var nx = Math.floor(Math.random() * 13) + 1, - ny = Math.floor(Math.random() * 13) + 1; - // 添加位置 绘制危险区域 - if (!locs.includes([nx, ny])) { - locs.push([nx, ny]); - // 横竖都要画 - for (var mx = 1; mx < 14; mx++) { - core.fillRect( - 'ballThunder' + now, - mx * 32 + 2, - ny * 32 + 2, - 28, - 28, - [190, 190, 255, 0.6] - ); - } - for (var my = 1; my < 14; my++) { - core.fillRect( - 'ballThunder' + now, - nx * 32 + 2, - my * 32 + 2, - 28, - 28, - [190, 190, 255, 0.6] - ); - } - } - now++; - if (now >= times) { - clearInterval(ballThunder); - setTimeout(() => { - thunderAnimate(locs); - }, 1000); - } - }, 200); - // 动画 伤害 - function thunderAnimate(locs) { - var frame = 0; - // 画布 - if (!core.dymCanvas.ballAnimate) - core.createCanvas('ballAnimate', 0, 0, 480, 480, 65); - else core.clearMap('ballAnimate'); - var style = core.dymCanvas.ballAnimate; - style.shadowColor = 'rgba(255, 255, 255, 1)'; - var damaged = []; - var animate = window.setInterval(() => { - core.clearMap('ballAnimate'); - for (var i = 0; i < locs.length; i++) { - style.shadowBlur = 16 * Math.random(); - // 错开执行动画 - if (frame - 10 * i > 0) { - var now = frame - 10 * i; - if (now == 1) core.playSound('electron.mp3'); - // 动画 - var nx = locs[i][0] * 32 + 16, - ny = locs[i][1] * 32 + 16; - if (now <= 2) { - core.fillCircle( - 'ballAnimate', - nx, - ny, - 16 + 3 * now, - [255, 255, 255, 0.9] - ); - } else { - // 上 - core.fillCircle( - 'ballAnimate', - nx, - ny - 4 * now, - 7 + 2 * Math.random(), - [255, 255, 255, 0.7] - ); - // 下 - core.fillCircle( - 'ballAnimate', - nx, - ny + 4 * now, - 7 + 2 * Math.random(), - [255, 255, 255, 0.7] - ); - // 左 - core.fillCircle( - 'ballAnimate', - nx - 4 * now, - ny, - 7 + 2 * Math.random(), - [255, 255, 255, 0.7] - ); - // 右 - core.fillCircle( - 'ballAnimate', - nx + 4 * now, - ny, - 7 + 2 * Math.random(), - [255, 255, 255, 0.7] - ); - } - // 清除危险区域 - core.clearMap( - 'ballThunder' + i, - nx - 16, - ny - 16 - 4 * now, - 32, - 32 - ); - core.clearMap( - 'ballThunder' + i, - nx - 16, - ny - 16 + 4 * now, - 32, - 32 - ); - core.clearMap( - 'ballThunder' + i, - nx - 16 - 4 * now, - ny - 16, - 32, - 32 - ); - core.clearMap( - 'ballThunder' + i, - nx - 16 + 4 * now, - ny - 16, - 32, - 32 - ); - // 伤害 - if (!damaged[i]) { - var x = core.status.hero.loc.x, - y = core.status.hero.loc.y; - if ( - ((Math.floor((nx - 16 - 4 * now) / 32) == x || - Math.floor((nx - 16 + 4 * now) / 32) == - x) && - locs[i][1] == y) || - ((Math.floor((ny - 16 - 4 * now) / 32) == y || - Math.floor((ny - 16 + 4 * now) / 32) == - y) && - locs[i][0] == x) - ) { - damaged[i] = true; - core.status.hero.hp -= 3000; - core.addPop(x * 32 + 16, y * 32 + 16, -3000); - core.updateStatusBar(); - core.playSound('electron.mp3'); - if (core.status.hero.hp < 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - clearInterval(animate); - return; - } - } - } - // 结束 - if (i == locs.length - 1 && now > 120) { - clearInterval(animate); - } - } - } - frame++; - }, 20); - } - } - // ------ 第三阶段 3500~0 ------ // - function startStage3() { - // 闪烁 - core.createCanvas('flash', 0, 0, 480, 480, 160); - var alpha = 0; - var frame = 0; - var start1 = window.setInterval(() => { - core.clearMap('flash'); - frame++; - if (frame <= 8) alpha += 0.125; - else alpha -= 0.01; - core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); - if (alpha == 0) { - clearInterval(start1); - core.deleteCanvas('flash'); - } - if (frame == 8) { - core.playSound('thunder.mp3'); - changeTerra(); - core.insertAction([{ type: 'changePos', loc: [7, 7] }]); - } - }); - // 改变地形 - function changeTerra() { - for (var nx = 0; nx < 15; nx++) { - for (var ny = 0; ny < 15; ny++) { - if (nx == 0 || nx == 14 || ny == 0 || ny == 14) { - core.removeBlock(nx, ny); - } - if ( - (nx == 1 || nx == 13 || ny == 1 || ny == 13) && - nx != 0 && - nx != 14 && - ny != 0 && - ny != 14 - ) { - core.setBlock(527, nx, ny); - } - } - } - core.createCanvas('tower7', 0, 0, 480, 480, 15); - // 画贴图 - core.drawImage( - 'tower7', - 'tower7.jpeg', - 360, - 0, - 32, - 480, - 0, - 0, - 32, - 480 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 840, - 0, - 32, - 480, - 448, - 0, - 32, - 480 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 392, - 0, - 416, - 32, - 32, - 0, - 416, - 32 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 392, - 448, - 416, - 32, - 32, - 448, - 416, - 32 - ); - core.setBlock('E557', 7, 2); - core.playBgm('towerBoss3.mp3'); - } - } - // 进入第四阶段 - function startStage4() { - // 闪烁 - core.createCanvas('flash', 0, 0, 480, 480, 160); - var alpha = 0; - var frame = 0; - var start1 = window.setInterval(() => { - core.clearMap('flash'); - frame++; - if (frame <= 8) alpha += 0.125; - else alpha -= 0.01; - core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); - if (alpha == 0) { - clearInterval(start1); - core.deleteCanvas('flash'); - } - if (frame == 8) { - core.playSound('thunder.mp3'); - changeTerra(); - core.insertAction([{ type: 'changePos', loc: [7, 7] }]); - } - }); - // 改变地形 - function changeTerra() { - for (var nx = 1; nx < 14; nx++) { - for (var ny = 1; ny < 14; ny++) { - if (nx == 1 || nx == 13 || ny == 1 || ny == 13) { - core.removeBlock(nx, ny); - } - if ( - (nx == 2 || nx == 12 || ny == 2 || ny == 12) && - nx != 1 && - nx != 13 && - ny != 1 && - ny != 13 - ) { - core.setBlock(527, nx, ny); - } - } - } - core.createCanvas('tower7', 0, 0, 480, 480, 15); - // 画贴图 - core.drawImage( - 'tower7', - 'tower7.jpeg', - 360, - 0, - 64, - 480, - 0, - 0, - 64, - 480 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 776, - 0, - 64, - 480, - 416, - 0, - 64, - 480 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 424, - 0, - 352, - 64, - 64, - 0, - 352, - 64 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 424, - 416, - 352, - 64, - 64, - 416, - 352, - 64 - ); - core.setBlock('E557', 7, 3); - } - } - // 进入第五阶段 - function startStage5() { - // 闪烁 - core.createCanvas('flash', 0, 0, 480, 480, 160); - var alpha = 0; - var frame = 0; - var start1 = window.setInterval(() => { - core.clearMap('flash'); - frame++; - if (frame <= 8) alpha += 0.125; - else alpha -= 0.01; - core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); - if (alpha == 0) { - clearInterval(start1); - core.deleteCanvas('flash'); - } - if (frame == 8) { - core.playSound('thunder.mp3'); - changeTerra(); - core.insertAction([{ type: 'changePos', loc: [7, 7] }]); - } - }); - // 改变地形 - function changeTerra() { - for (var nx = 2; nx < 13; nx++) { - for (var ny = 2; ny < 13; ny++) { - if (nx == 2 || nx == 12 || ny == 2 || ny == 12) { - core.removeBlock(nx, ny); - } - if ( - (nx == 3 || nx == 11 || ny == 3 || ny == 11) && - nx != 2 && - nx != 12 && - ny != 2 && - ny != 12 - ) { - core.setBlock(527, nx, ny); - } - } - } - core.createCanvas('tower7', 0, 0, 480, 480, 15); - // 画贴图 - core.drawImage( - 'tower7', - 'tower7.jpeg', - 360, - 0, - 96, - 480, - 0, - 0, - 96, - 480 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 744, - 0, - 96, - 480, - 384, - 0, - 96, - 480 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 456, - 0, - 288, - 96, - 96, - 0, - 288, - 96 - ); - core.drawImage( - 'tower7', - 'tower7.jpeg', - 456, - 384, - 288, - 96, - 96, - 384, - 288, - 96 - ); - core.setBlock('E557', 7, 4); - } - } - // 链状闪电 随机连接 碰到勇士则受伤 - function chainThunder() { - // 随机次数 - var times = Math.ceil(Math.random() * 6) + 3; - // 画布 - if (!core.dymCanvas.chainDanger) - core.createCanvas('chainDanger', 0, 0, 480, 480, 35); - else core.clearMap('chainDanger'); - // setInterval执行 - var locs = [], - now = 0; - var chain = window.setInterval(() => { - if (hp > 2000) { - var nx = Math.floor(Math.random() * 11) + 2, - ny = Math.floor(Math.random() * 11) + 2; - } else if (hp > 1000) { - var nx = Math.floor(Math.random() * 9) + 3, - ny = Math.floor(Math.random() * 9) + 3; - } else { - var nx = Math.floor(Math.random() * 7) + 4, - ny = Math.floor(Math.random() * 7) + 4; - } - if (!locs.includes([nx, ny])) { - locs.push([nx, ny]); - } else return; - // 危险线 - if (now > 0) { - core.drawLine( - 'chainDanger', - locs[now - 1][0] * 32 + 16, - locs[now - 1][1] * 32 + 16, - nx * 32 + 16, - ny * 32 + 16, - [220, 100, 255, 0.6], - 3 - ); - } - if (now >= times) { - clearInterval(chain); - setTimeout(() => { - getChainRoute(locs); - core.deleteCanvas('chainDanger'); - }, 1000); - } - now++; - }, 100); - } - // 链状闪电 动画 - function chainAnimate(route) { - if (!route) return chainThunder(); - // 画布 - if (!core.dymCanvas.chain) - core.createCanvas('chain', 0, 0, 480, 480, 65); - else core.clearMap('chain'); - var style = core.dymCanvas.chain; - style.shadowBlur = 3; - style.shadowColor = 'rgba(255, 255, 255, 1)'; - style.filter = 'blur(2px)'; - // 当然还是setInterval - var frame = 0, - now = 0; - var animate = window.setInterval(() => { - if (now >= route.length - 1) { - clearInterval(animate); - setTimeout(() => { - core.deleteCanvas('chain'); - }, 1000); - return; - } - frame++; - if (frame % 2 != 0) return; - core.drawLine( - 'chain', - route[now][0], - route[now][1], - route[now + 1][0], - route[now + 1][1], - '#ffffff', - 3 - ); - // 节点 - if (now == 0) { - core.fillCircle( - 'chain', - route[0][0], - route[0][1], - 7, - '#ffffff' - ); - } - if ( - (route[now + 1][0] - 16) % 32 == 0 && - (route[now + 1][1] - 16) % 32 == 0 - ) { - core.fillCircle( - 'chain', - route[now + 1][0], - route[now + 1][1], - 7, - '#ffffff' - ); - } - // 判断伤害 - lineDamage( - route[now][0], - route[now][1], - route[now + 1][0], - route[now + 1][1], - 4000 - ); - now++; - }, 20); - } - // 链状闪电 获得闪电路径 - function getChainRoute(locs) { - // 照样用setInterval - var now = 0, - routes = []; - var route = window.setInterval(() => { - var nx = locs[now][0] * 32 + 16, - ny = locs[now][1] * 32 + 16; - var tx = locs[now + 1][0] * 32 + 16, - ty = locs[now + 1][1] * 32 + 16; - var dx = tx - nx, - dy = ty - ny; - var angle = Math.atan(dy / dx); - if (dy < 0 && dx < 0) angle += Math.PI; - if (dx < 0 && dy > 0) angle += Math.PI; - // 循环 + 随机 - var times = 0; - while (true) { - times++; - nx += Math.random() * 50 * Math.cos(angle); - ny += Math.random() * 50 * Math.sin(angle); - routes.push([nx, ny]); - if ( - Math.sqrt(Math.pow(ny - ty, 2) + Math.pow(nx - tx, 2)) <= - 100 - ) { - routes.push([tx, ty]); - break; - } - if (times >= 20) { - clearInterval(route); - routes = null; - return; - } - } - now++; - if (now >= locs.length - 1) { - clearInterval(route); - chainAnimate(routes); - } - }, 2); - } - // 随机轰炸 - function randomBoom() { - // 停止轰炸 - if (!flags.booming) { - clearInterval(flags.boom); + }, 20); + // 实时检测勇士位置 + var frame2 = 0; + var atkBoss = window.setInterval(() => { + frame2++; + var x = core.status.hero.loc.x, + y = core.status.hero.loc.y; + // 2秒超时 + if (frame2 > 100) { + setTimeout(() => { + delete flags.canAttack; + }, 4000); + clearInterval(atkBoss); + core.deleteCanvas('attackBoss'); return; } - // 根据阶段数 分攻击速率 和范围 - var boomTime; - var range; - if (hp > 2000) { - boomTime = 500; - range = 11; - } else if (hp > 1000) { - boomTime = 400; - range = 9; - } else { - boomTime = 300; - range = 7; + if (nx == x && ny == y) { + setTimeout(() => { + delete flags.canAttack; + }, 4000); + dynamicChangeHp(hp, hp - 500, 10000); + hp -= 500; + clearInterval(atkBoss); + core.deleteCanvas('attackBoss'); + if (hp > 3500) core.drawAnimate('hand', 7, 1); + else if (hp > 2000) core.drawAnimate('hand', 7, 2); + else if (hp > 1000) core.drawAnimate('hand', 7, 3); + else core.drawAnimate('hand', 7, 4); + return; } - // setInterval - flags.boom = window.setInterval(() => { - var nx = Math.floor(Math.random() * range) + (15 - range) / 2, - ny = Math.floor(Math.random() * range) + (15 - range) / 2; - boomLocs.push([nx, ny, 0]); - if (!flags.booming) clearInterval(flags.boom); - }, boomTime); - // 动画要在这里调用 - boomingAnimate(); - } - // 随机轰炸 动画 - function boomingAnimate() { - // 直接setInterval - if (!core.dymCanvas.boom) core.createCanvas('boom', 0, 0, 480, 480, 65); - else core.clearMap('boom'); - var boomAnimate = window.setInterval(() => { - if (boomLocs.length == 0) return; - if (!flags.booming && boomLocs.length == 0) { - clearInterval(boomAnimate); - return; + }, 20); +} +// 核心函数 +function bossCore() { + var interval = window.setInterval(() => { + if (stage == 1) { + if (seconds == 8) skipWord('智慧之神:果然,你和别人不一样。'); + if (seconds == 12) skipWord('智慧之神:你知道去躲避那些攻击。'); + if (seconds == 16) + skipWord( + '智慧之神:之前的那些人总会一头撞上我的攻击,悲剧收场。' + ); + if (seconds == 20) + skipWord('提示:踩在红圈上可以对智慧之神造成伤害'); + if (seconds > 10) attackBoss(); + if (seconds % 10 == 0) intelligentArrow(); + if (seconds % 7 == 0 && seconds != 0) intelligentDoor(); + if (seconds > 20 && seconds % 13 == 0) icyMomentem(); + } + if (stage == 1 && hp <= 7000) { + stage++; + seconds = 0; + skipWord('智慧之神:不错小伙子'); + core.pauseBgm(); + } + if (stage == 2) { + if (seconds == 4) skipWord('智慧之神:你的确拥有智慧。'); + if (seconds == 8) skipWord('智慧之神:或许你就是那个未来的救星。'); + if (seconds == 12) skipWord('智慧之神:不过,这场战斗才刚刚开始'); + if (seconds == 25) skipWord('提示:方形区域均为危险区域'); + if (seconds == 15) + setTimeout(() => { + core.playSound('thunder.mp3'); + }, 500); + if (seconds == 16) startStage2(); + if (seconds > 20) attackBoss(); + if (seconds % 4 == 0 && seconds > 20) randomThunder(); + if (seconds > 30 && seconds % 12 == 0) ballThunder(); + } + if (hp <= 3500 && stage == 2) { + stage++; + seconds = 0; + skipWord('智慧之神:不得不说小伙子'); + core.pauseBgm(); + } + if (stage >= 3) { + if (seconds == 4) skipWord('智慧之神:拥有智慧就是不一样。'); + if (seconds == 8) skipWord('智慧之神:不过,你还得再过我一关!'); + if (seconds == 12) startStage3(); + if (seconds == 15) { + flags.booming = true; + randomBoom(); } - core.clearMap('boom'); - boomLocs.forEach((loc, index) => { - loc[2]++; - var x = loc[0] * 32 + 16, - y = loc[1] * 32 + 16; - if (loc[2] >= 20) { - var alpha = 1, - radius = 12; - } else { - var radius = 0.12 * Math.pow(20 - loc[2], 2) + 12, - alpha = Math.max(1, 2 - loc[2] * 0.1); + if (seconds > 20) attackBoss(); + if (seconds > 20 && seconds % 10 == 0) chainThunder(); + if (hp == 2000 && stage == 3) { + stage++; + flags.booming = false; + skipWord('智慧之神:还没有结束!'); + startStage4(); + setTimeout(() => { + flags.booming = true; + randomBoom(); + }, 5000); + } + if (hp == 1000 && stage == 4) { + stage++; + flags.booming = false; + skipWord('智慧之神:还没有结束!!!!!!'); + startStage5(); + setTimeout(() => { + flags.booming = true; + randomBoom(); + }, 5000); + } + } + if (hp == 0) { + clearInterval(interval); + clearInterval(flags.boom); + core.status.hero.hp = heroHp; + core.plugin.towerBoss.autoFixRouteBoss(false); + delete flags.__bgm__; + core.pauseBgm(); + core.insertAction([ + '\t[智慧之神,E557]\b[down,7,4]看来你真的会成为那个拯救未来的人。', + '\t[智慧之神,E557]\b[down,7,4]记住,拥有智慧便可以掌控万物。', + '\t[低级智人]\b[up,hero]智慧?智慧到底是什么?', + '\t[智慧之神,E557]\b[down,7,4]最终,你会知道答案的。', + '\t[智慧之神,E557]\b[down,7,4]继续向东前进吧,那里能找到你想要的答案。', + { type: 'openDoor', loc: [13, 6], floorId: 'MT19' }, + '\t[智慧之神,E557]\b[down,7,4]我这就把你送出去', + { type: 'setValue', name: 'flag:boss1', value: 'true' }, + { type: 'changeFloor', floorId: 'MT20', loc: [7, 9] }, + { type: 'forbidSave' }, + { type: 'showStatusBar' }, + { + type: 'function', + function: '() => {\ncore.deleteAllCanvas();\n}' } - var angle = (loc[2] * Math.PI) / 50; - // 开始绘制 - core.fillCircle('boom', x, y, 3, [255, 50, 50, alpha]); - core.strokeCircle( - 'boom', - x, - y, - radius, - [255, 50, 50, alpha], - 2 - ); - // 旋转的线 - core.drawLine( - 'boom', - x + radius * Math.cos(angle), - y + radius * Math.sin(angle), - x + (radius + 15) * Math.cos(angle), - y + (radius + 15) * Math.sin(angle), - [255, 50, 50, alpha], - 1 - ); - angle += Math.PI; - core.drawLine( - 'boom', - x + radius * Math.cos(angle), - y + radius * Math.sin(angle), - x + (radius + 15) * Math.cos(angle), - y + (radius + 15) * Math.sin(angle), - [255, 50, 50, alpha], - 1 - ); - // 炸弹 下落 - if (loc[2] > 70) { - var h = - y - - (20 * (85 - loc[2]) + 2.8 * Math.pow(85 - loc[2], 2)); - core.drawImage('boom', 'boom.png', x - 18, h - 80, 36, 80); - } - if (loc[2] == 85) { - core.drawAnimate( - 'explosion1', - (x - 16) / 32, - (y - 16) / 32 - ); - boomLocs.splice(index, 1); - if (boomLocs.length == 0) core.deleteCanvas('boom'); - // 伤害判定 - var hx = core.status.hero.loc.x, - hy = core.status.hero.loc.y; - if (loc[0] == hx && loc[1] == hy) { - core.status.hero.hp -= 3000; - core.addPop(x * 32 + 16, y * 32 + 16, -3000); + ]); + } + seconds++; + }, 1000); +} +// ------ 第一阶段 10000~7000血 ------ // +// 技能1 智慧之箭 1000伤害 +function intelligentArrow(fromSelf) { + // 坐标 + var loc = Math.floor(Math.random() * 13 + 1); + var direction = Math.random() > 0.5 ? 'horizon' : 'vertical'; + // 执行次数 + if (!fromSelf) { + var times = Math.ceil(Math.random() * 8) + 4; + var nowTime = 1; + var times1 = window.setInterval(() => { + intelligentArrow(true); + nowTime++; + if (nowTime >= times) { + clearInterval(times1); + } + }, 200); + } + // 防重复 + if (core.dymCanvas['inteArrow' + loc + direction]) + return intelligentArrow(true); + // 危险区域 + if (!core.dymCanvas.danger1) + core.createCanvas('danger1', 0, 0, 480, 480, 35); + if (direction == 'horizon') { + for (var nx = 1; nx < 14; nx++) { + core.fillRect( + 'danger1', + nx * 32 + 2, + loc * 32 + 2, + 28, + 28, + [255, 0, 0, 0.6] + ); + } + } else { + for (var ny = 1; ny < 14; ny++) { + core.fillRect( + 'danger1', + loc * 32 + 2, + ny * 32 + 2, + 28, + 28, + [255, 0, 0, 0.6] + ); + } + } + // 箭 + if (!core.dymCanvas['inteArrow' + loc + direction]) + core.createCanvas('inteArrow' + loc + direction, 0, 0, 544, 544, 65); + core.clearMap('inteArrow' + loc + direction); + if (direction == 'horizon') + core.drawImage( + 'inteArrow' + loc + direction, + 'arrow.png', + 448, + loc * 32, + 102, + 32 + ); + else + core.drawImage( + 'inteArrow' + loc + direction, + 'arrow.png', + 0, + 0, + 259, + 75, + loc * 32 - 32, + 480, + 102, + 32, + Math.PI / 2 + ); + // 动画与伤害函数 + setTimeout(() => { + core.playSound('arrow.mp3'); + core.deleteCanvas('danger1'); + // 动画效果 + var nloc = 0, + speed = 0; + var damaged = {}; + var skill1 = window.setInterval(() => { + speed -= 1; + nloc += speed; + if (direction == 'horizon') + core.relocateCanvas('inteArrow' + loc + direction, nloc, 0); + else core.relocateCanvas('inteArrow' + loc + direction, 0, nloc); + if (nloc < -480) { + core.deleteCanvas('inteArrow' + loc + direction); + clearInterval(skill1); + } + // 伤害判定 + if (!damaged[loc + direction]) { + var x = core.status.hero.loc.x, + y = core.status.hero.loc.y; + if (direction == 'horizon') { + if (y == loc && Math.floor((480 + nloc) / 32) == x) { + damaged[loc + direction] = true; + core.drawHeroAnimate('hand'); + core.status.hero.hp -= 1000; + core.addPop(x * 32 + 16, y * 32 + 16, -1000); core.updateStatusBar(); if (core.status.hero.hp < 0) { + clearInterval(skill1); + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + return; + } + } + } else { + if (x == loc && Math.floor((480 + nloc) / 32) == y) { + damaged[loc + direction] = true; + core.drawHeroAnimate('hand'); + core.status.hero.hp -= 1000; + core.addPop(x * 32 + 16, y * 32 + 16, -1000); + core.updateStatusBar(); + if (core.status.hero.hp < 0) { + clearInterval(skill1); core.status.hero.hp = 0; core.updateStatusBar(); core.events.lose(); - clearInterval(boomAnimate); - flags.booming = false; return; } } } - }); + } }, 20); - } - // 直线型伤害判定 - function lineDamage(x1, y1, x2, y2, damage) { - // 获得勇士坐标 - var x = core.status.hero.loc.x, - y = core.status.hero.loc.y; - // 是否可能碰到勇士 - if ( - (x1 < x * 32 - 12 && x2 < x * 32 - 12) || - (x1 > x * 32 + 12 && x2 > x * 32 + 12) || - (y1 < y * 32 - 16 && y2 < y * 32 - 16) || - (y1 > y * 32 + 16 && y2 > y * 32 + 16) - ) + }, 3000); +} +// 技能2 智慧之门 随机传送 +function intelligentDoor() { + if (Math.random() < 0.5) return; + // 随机位置 + var toX = Math.floor(Math.random() * 13) + 1, + toY = Math.floor(Math.random() * 13) + 1; + // 在勇士身上绘制动画 + core.drawHeroAnimate('magicAtk'); + // 在目标位置绘制动画 + if (!core.dymCanvas['door' + toX + '_' + toY]) + core.createCanvas('door' + toX + '_' + toY, 0, 0, 480, 480, 35); + else core.clearMap('door' + toX + '_' + toY); + var style = document + .getElementById('door' + toX + '_' + toY) + .getContext('2d'); + var frame = 0, + width = 0, + a = 0.0128, + speed = 0.64; + // 动画 + var skill2 = window.setInterval(() => { + frame++; + if (frame < 40) return; + if (frame == 100) { + clearInterval(skill2); + // 执行传送 + core.insertAction([{ type: 'changePos', loc: [toX, toY] }]); + // 删除传送门 + setTimeout(() => { + core.deleteCanvas('door' + toX + '_' + toY); + }, 2000); return; - // 对角线的端点是否在直线异侧 勇士视为24 * 32 - for (var time = 1; time <= 2; time++) { - // 左下右上 - if (time == 1) { - var loc1 = [x * 32 - 12, y * 32 + 16], - loc2 = [x * 32 + 12, y * 32 - 16]; - // 直线方程 y == (y2 - y1) / (x2 - x1) * (x - x1) + y1 - var n1 = - ((y2 - y1) / (x2 - x1)) * (loc1[0] - x1) + y1 - loc1[1], - n2 = - ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1]; - if (n1 * n2 <= 0) { - core.status.hero.hp -= damage; - core.addPop(x * 32 + 16, y * 32 + 16, -damage); + } + width += speed * 2; + speed -= a; + core.clearMap('door' + toX + '_' + toY); + style.shadowColor = 'rgba(255, 255, 255, 1)'; + style.shadowBlur = 7; + style.filter = 'blur(5px)'; + core.fillRect( + 'door' + toX + '_' + toY, + toX * 32, + toY * 32 - 24, + width, + 48, + [255, 255, 255, 0.7] + ); + style.shadowColor = 'rgba(0, 0, 0, 0.5)'; + style.filter = 'blur(3px)'; + core.strokeRect( + 'door' + toX + '_' + toY, + toX * 32, + toY * 32 - 24, + width, + 48, + [255, 255, 255, 0.7], + 3 + ); + }, 20); +} +// 技能3 万冰之势 全屏随机转换滑冰 如果转换时在滑冰上造成5000点伤害 +function icyMomentem() { + if (flags.haveIce) return; + if (Math.random() < 0.5) return; + var times = Math.floor(Math.random() * 100); + // 防卡 就setInterval吧 + var locs = [], + now = 0; + flags.haveIce = true; + if (!core.dymCanvas.icyMomentem) + core.createCanvas('icyMomentem', 0, 0, 480, 480, 35); + else core.clearMap('icyMomentem'); + var skill3 = window.setInterval(() => { + var nx = Math.floor(Math.random() * 13) + 1, + ny = Math.floor(Math.random() * 13) + 1; + if (!locs.includes([nx, ny])) { + locs.push([nx, ny]); + core.fillRect( + 'icyMomentem', + locs[now][0] * 32 + 2, + locs[now][1] * 32 + 2, + 28, + 28, + [150, 150, 255, 0.6] + ); + } + if (now == times) { + clearInterval(skill3); + skill3Effect(); + } + now++; + }, 20); + // 动画和伤害函数 + function skill3Effect() { + // 防卡 setInterval + var index = 0; + var effect = window.setInterval(() => { + var x = core.status.hero.loc.x, + y = core.status.hero.loc.y; + core.clearMap( + 'icyMomentem', + locs[index][0] * 32, + locs[index][1] * 32, + 32, + 32 + ); + core.setBgFgBlock('bg', 167, locs[index][0], locs[index][1]); + core.drawAnimate('ice', locs[index][0], locs[index][1]); + if (x == locs[index][0] && y == locs[index][1]) { + core.drawHeroAnimate('hand'); + core.status.hero.hp -= 5000; + core.addPop(x * 32 + 16, y * 32 + 16, -5000); + core.updateStatusBar(); + if (core.status.hero.hp < 0) { + core.status.hero.hp = 0; core.updateStatusBar(); - core.playSound('electron.mp3'); - if (core.status.hero.hp < 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - return; - } - return; - } - } else { - // 左上右下 - var loc1 = [x * 32 - 12, y * 32 - 16], - loc2 = [x * 32 + 12, y * 32 + 16]; - // 直线方程 y == (y2 - y1) / (x2 - x1) * (x - x1) + y1 - var n1 = - ((y2 - y1) / (x2 - x1)) * (loc1[0] - x1) + y1 - loc1[1], - n2 = - ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1]; - if (n1 * n2 <= 0) { - core.status.hero.hp -= damage; - core.addPop(x * 32 + 16, y * 32 + 16, -damage); - core.updateStatusBar(); - core.playSound('electron.mp3'); - if (core.status.hero.hp < 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - return; - } + core.events.lose(); + clearInterval(effect); return; } } + if (index >= locs.length - 1) { + clearInterval(effect); + setTimeout(() => { + deleteIce(locs); + }, 5000); + } + index++; + }, 50); + } + // 删除函数 + function deleteIce(locs) { + // 照样 setInterval + var index = 0; + var deleteIce = window.setInterval(() => { + core.setBgFgBlock('bg', 0, locs[index][0], locs[index][1]); + index++; + if (index >= locs.length) { + clearInterval(deleteIce); + core.deleteCanvas('icyMomentem'); + setTimeout(() => { + delete flags.haveIce; + }, 5000); + } + }, 50); + } +} +// ------ 第二阶段 7000~3500 ------ // +// 开始第二阶段 +function startStage2() { + // 闪烁 + core.createCanvas('flash', 0, 0, 480, 480, 160); + var alpha = 0; + var frame = 0; + var start1 = window.setInterval(() => { + core.clearMap('flash'); + frame++; + if (frame <= 8) alpha += 0.125; + else alpha -= 0.01; + core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); + if (alpha == 0) { + clearInterval(start1); + core.deleteCanvas('flash'); + } + if (frame == 8) { + changeWeather(); + } + }); + // 切换天气 + function changeWeather() { + core.setWeather(); + core.setWeather('rain', 10); + core.setWeather('fog', 8); + // 色调也得换 + core.setCurtain([0, 0, 0, 0.3]); + // bgm + core.playBgm('towerBoss2.mp3'); + } +} +// ----- 打雷相关 ----- // +// 随机打雷 +function randomThunder() { + var x = Math.floor(Math.random() * 13) + 1, + y = Math.floor(Math.random() * 13) + 1, + power = Math.ceil(Math.random() * 6); + // 绘制危险区域 + if (!core.dymCanvas.thunderDanger) + core.createCanvas('thunderDanger', 0, 0, 480, 480, 35); + else core.clearMap('thunderDanger'); + // 3*3范围 + for (var nx = x - 1; nx <= x + 1; nx++) { + for (var ny = y - 1; ny <= y + 1; ny++) { + core.fillRect( + 'thunderDanger', + nx * 32 + 2, + ny * 32 + 2, + 28, + 28, + [255, 255, 255, 0.6] + ); } } + core.deleteCanvas('flash'); + setTimeout(() => { + core.playSound('thunder.mp3'); + }, 500); + setTimeout(() => { + core.deleteCanvas('thunderDanger'); + drawThunder(x, y, power); + }, 1000); +} +// 绘制 +function drawThunder(x, y, power) { + var route = getThunderRoute(x * 32 + 16, y * 32 + 16, power); + // 开始绘制 + if (!core.dymCanvas.thunder) + core.createCanvas('thunder', 0, 0, 480, 480, 65); + else core.clearMap('thunder'); + var style = core.dymCanvas.thunder; + style.shadowColor = 'rgba(220, 220, 255, 1)'; + style.shadowBlur = power; + style.filter = 'blur(2.5px)'; + for (var num in route) { + // 一个个绘制 + for (var i = 0; i < route[num].length - 1; i++) { + var now = route[num][i], + next = route[num][i + 1]; + core.drawLine( + 'thunder', + now[0], + now[1], + next[0], + next[1], + '#ffffff', + 2.5 + ); + } + } + // 伤害 + getThunderRoute(x, y, power); + // 闪一下 + var frame1 = 0, + alpha = 0.5; + if (!core.dymCanvas.flash) core.createCanvas('flash', 0, 0, 480, 480, 160); + else core.clearMap('flash'); + var thunderFlash = window.setInterval(() => { + alpha -= 0.05; + frame1++; + core.clearMap('flash'); + core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); + if (frame1 >= 10) { + clearInterval(thunderFlash); + core.deleteCanvas('flash'); + // 删除闪电 + setTimeout(() => { + core.deleteCanvas('thunder'); + }, 700); + } + }, 20); +} +// 获得雷电路径 +function getThunderRoute(x, y, power) { + var route = []; + for (var num = 0; num < power; num++) { + var nx = x, + ny = y; + route[num] = []; + for (var i = 0; ny >= 0; i++) { + if (i > 0) { + nx += Math.random() * 30 - 15; + ny -= Math.random() * 80 + 30; + } else { + nx += Math.random() * 16 - 8; + ny += Math.random() * 16 - 8; + } + route[num].push([nx, ny]); + } + } + return route; +} +// 打雷伤害判定 +function getThunderDamage(x, y, power) { + var hx = core.status.hero.loc.x, + hy = core.status.hero.loc.y; + if (Math.abs(hx - x) <= 1 && Math.abs(hy - y) <= 1) { + core.status.hero.hp -= 3000 * power; + core.addPop(x * 32 + 16, y * 32 + 16, -3000 * power); + core.updateStatusBar(); + if (core.status.hero.hp < 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + return; + } + } +} +// ----- 打雷 END ----- // +// 球形闪电 横竖 +function ballThunder() { + // 随机数量 + var times = Math.ceil(Math.random() * 12) + 6; + var now = 0, + locs = []; + // setInterval执行 + var ballThunder = window.setInterval(() => { + // 画布 + if (!core.dymCanvas['ballThunder' + now]) + core.createCanvas('ballThunder' + now, 0, 0, 480, 480, 35); + else core.clearMap('ballThunder' + now); + var nx = Math.floor(Math.random() * 13) + 1, + ny = Math.floor(Math.random() * 13) + 1; + // 添加位置 绘制危险区域 + if (!locs.includes([nx, ny])) { + locs.push([nx, ny]); + // 横竖都要画 + for (var mx = 1; mx < 14; mx++) { + core.fillRect( + 'ballThunder' + now, + mx * 32 + 2, + ny * 32 + 2, + 28, + 28, + [190, 190, 255, 0.6] + ); + } + for (var my = 1; my < 14; my++) { + core.fillRect( + 'ballThunder' + now, + nx * 32 + 2, + my * 32 + 2, + 28, + 28, + [190, 190, 255, 0.6] + ); + } + } + now++; + if (now >= times) { + clearInterval(ballThunder); + setTimeout(() => { + thunderAnimate(locs); + }, 1000); + } + }, 200); + // 动画 伤害 + function thunderAnimate(locs) { + var frame = 0; + // 画布 + if (!core.dymCanvas.ballAnimate) + core.createCanvas('ballAnimate', 0, 0, 480, 480, 65); + else core.clearMap('ballAnimate'); + var style = core.dymCanvas.ballAnimate; + style.shadowColor = 'rgba(255, 255, 255, 1)'; + var damaged = []; + var animate = window.setInterval(() => { + core.clearMap('ballAnimate'); + for (var i = 0; i < locs.length; i++) { + style.shadowBlur = 16 * Math.random(); + // 错开执行动画 + if (frame - 10 * i > 0) { + var now = frame - 10 * i; + if (now == 1) core.playSound('electron.mp3'); + // 动画 + var nx = locs[i][0] * 32 + 16, + ny = locs[i][1] * 32 + 16; + if (now <= 2) { + core.fillCircle( + 'ballAnimate', + nx, + ny, + 16 + 3 * now, + [255, 255, 255, 0.9] + ); + } else { + // 上 + core.fillCircle( + 'ballAnimate', + nx, + ny - 4 * now, + 7 + 2 * Math.random(), + [255, 255, 255, 0.7] + ); + // 下 + core.fillCircle( + 'ballAnimate', + nx, + ny + 4 * now, + 7 + 2 * Math.random(), + [255, 255, 255, 0.7] + ); + // 左 + core.fillCircle( + 'ballAnimate', + nx - 4 * now, + ny, + 7 + 2 * Math.random(), + [255, 255, 255, 0.7] + ); + // 右 + core.fillCircle( + 'ballAnimate', + nx + 4 * now, + ny, + 7 + 2 * Math.random(), + [255, 255, 255, 0.7] + ); + } + // 清除危险区域 + core.clearMap( + 'ballThunder' + i, + nx - 16, + ny - 16 - 4 * now, + 32, + 32 + ); + core.clearMap( + 'ballThunder' + i, + nx - 16, + ny - 16 + 4 * now, + 32, + 32 + ); + core.clearMap( + 'ballThunder' + i, + nx - 16 - 4 * now, + ny - 16, + 32, + 32 + ); + core.clearMap( + 'ballThunder' + i, + nx - 16 + 4 * now, + ny - 16, + 32, + 32 + ); + // 伤害 + if (!damaged[i]) { + var x = core.status.hero.loc.x, + y = core.status.hero.loc.y; + if ( + ((Math.floor((nx - 16 - 4 * now) / 32) == x || + Math.floor((nx - 16 + 4 * now) / 32) == x) && + locs[i][1] == y) || + ((Math.floor((ny - 16 - 4 * now) / 32) == y || + Math.floor((ny - 16 + 4 * now) / 32) == y) && + locs[i][0] == x) + ) { + damaged[i] = true; + core.status.hero.hp -= 3000; + core.addPop(x * 32 + 16, y * 32 + 16, -3000); + core.updateStatusBar(); + core.playSound('electron.mp3'); + if (core.status.hero.hp < 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + clearInterval(animate); + return; + } + } + } + // 结束 + if (i == locs.length - 1 && now > 120) { + clearInterval(animate); + } + } + } + frame++; + }, 20); + } +} +// ------ 第三阶段 3500~0 ------ // +function startStage3() { + // 闪烁 + core.createCanvas('flash', 0, 0, 480, 480, 160); + var alpha = 0; + var frame = 0; + var start1 = window.setInterval(() => { + core.clearMap('flash'); + frame++; + if (frame <= 8) alpha += 0.125; + else alpha -= 0.01; + core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); + if (alpha == 0) { + clearInterval(start1); + core.deleteCanvas('flash'); + } + if (frame == 8) { + core.playSound('thunder.mp3'); + changeTerra(); + core.insertAction([{ type: 'changePos', loc: [7, 7] }]); + } + }); + // 改变地形 + function changeTerra() { + for (var nx = 0; nx < 15; nx++) { + for (var ny = 0; ny < 15; ny++) { + if (nx == 0 || nx == 14 || ny == 0 || ny == 14) { + core.removeBlock(nx, ny); + } + if ( + (nx == 1 || nx == 13 || ny == 1 || ny == 13) && + nx != 0 && + nx != 14 && + ny != 0 && + ny != 14 + ) { + core.setBlock(527, nx, ny); + } + } + } + core.createCanvas('tower7', 0, 0, 480, 480, 15); + // 画贴图 + core.drawImage('tower7', 'tower7.jpeg', 360, 0, 32, 480, 0, 0, 32, 480); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 840, + 0, + 32, + 480, + 448, + 0, + 32, + 480 + ); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 392, + 0, + 416, + 32, + 32, + 0, + 416, + 32 + ); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 392, + 448, + 416, + 32, + 32, + 448, + 416, + 32 + ); + core.setBlock('E557', 7, 2); + core.playBgm('towerBoss3.mp3'); + } +} +// 进入第四阶段 +function startStage4() { + // 闪烁 + core.createCanvas('flash', 0, 0, 480, 480, 160); + var alpha = 0; + var frame = 0; + var start1 = window.setInterval(() => { + core.clearMap('flash'); + frame++; + if (frame <= 8) alpha += 0.125; + else alpha -= 0.01; + core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); + if (alpha == 0) { + clearInterval(start1); + core.deleteCanvas('flash'); + } + if (frame == 8) { + core.playSound('thunder.mp3'); + changeTerra(); + core.insertAction([{ type: 'changePos', loc: [7, 7] }]); + } + }); + // 改变地形 + function changeTerra() { + for (var nx = 1; nx < 14; nx++) { + for (var ny = 1; ny < 14; ny++) { + if (nx == 1 || nx == 13 || ny == 1 || ny == 13) { + core.removeBlock(nx, ny); + } + if ( + (nx == 2 || nx == 12 || ny == 2 || ny == 12) && + nx != 1 && + nx != 13 && + ny != 1 && + ny != 13 + ) { + core.setBlock(527, nx, ny); + } + } + } + core.createCanvas('tower7', 0, 0, 480, 480, 15); + // 画贴图 + core.drawImage('tower7', 'tower7.jpeg', 360, 0, 64, 480, 0, 0, 64, 480); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 776, + 0, + 64, + 480, + 416, + 0, + 64, + 480 + ); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 424, + 0, + 352, + 64, + 64, + 0, + 352, + 64 + ); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 424, + 416, + 352, + 64, + 64, + 416, + 352, + 64 + ); + core.setBlock('E557', 7, 3); + } +} +// 进入第五阶段 +function startStage5() { + // 闪烁 + core.createCanvas('flash', 0, 0, 480, 480, 160); + var alpha = 0; + var frame = 0; + var start1 = window.setInterval(() => { + core.clearMap('flash'); + frame++; + if (frame <= 8) alpha += 0.125; + else alpha -= 0.01; + core.fillRect('flash', 0, 0, 480, 480, [255, 255, 255, alpha]); + if (alpha == 0) { + clearInterval(start1); + core.deleteCanvas('flash'); + } + if (frame == 8) { + core.playSound('thunder.mp3'); + changeTerra(); + core.insertAction([{ type: 'changePos', loc: [7, 7] }]); + } + }); + // 改变地形 + function changeTerra() { + for (var nx = 2; nx < 13; nx++) { + for (var ny = 2; ny < 13; ny++) { + if (nx == 2 || nx == 12 || ny == 2 || ny == 12) { + core.removeBlock(nx, ny); + } + if ( + (nx == 3 || nx == 11 || ny == 3 || ny == 11) && + nx != 2 && + nx != 12 && + ny != 2 && + ny != 12 + ) { + core.setBlock(527, nx, ny); + } + } + } + core.createCanvas('tower7', 0, 0, 480, 480, 15); + // 画贴图 + core.drawImage('tower7', 'tower7.jpeg', 360, 0, 96, 480, 0, 0, 96, 480); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 744, + 0, + 96, + 480, + 384, + 0, + 96, + 480 + ); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 456, + 0, + 288, + 96, + 96, + 0, + 288, + 96 + ); + core.drawImage( + 'tower7', + 'tower7.jpeg', + 456, + 384, + 288, + 96, + 96, + 384, + 288, + 96 + ); + core.setBlock('E557', 7, 4); + } +} +// 链状闪电 随机连接 碰到勇士则受伤 +function chainThunder() { + // 随机次数 + var times = Math.ceil(Math.random() * 6) + 3; + // 画布 + if (!core.dymCanvas.chainDanger) + core.createCanvas('chainDanger', 0, 0, 480, 480, 35); + else core.clearMap('chainDanger'); + // setInterval执行 + var locs = [], + now = 0; + var chain = window.setInterval(() => { + if (hp > 2000) { + var nx = Math.floor(Math.random() * 11) + 2, + ny = Math.floor(Math.random() * 11) + 2; + } else if (hp > 1000) { + var nx = Math.floor(Math.random() * 9) + 3, + ny = Math.floor(Math.random() * 9) + 3; + } else { + var nx = Math.floor(Math.random() * 7) + 4, + ny = Math.floor(Math.random() * 7) + 4; + } + if (!locs.includes([nx, ny])) { + locs.push([nx, ny]); + } else return; + // 危险线 + if (now > 0) { + core.drawLine( + 'chainDanger', + locs[now - 1][0] * 32 + 16, + locs[now - 1][1] * 32 + 16, + nx * 32 + 16, + ny * 32 + 16, + [220, 100, 255, 0.6], + 3 + ); + } + if (now >= times) { + clearInterval(chain); + setTimeout(() => { + getChainRoute(locs); + core.deleteCanvas('chainDanger'); + }, 1000); + } + now++; + }, 100); +} +// 链状闪电 动画 +function chainAnimate(route) { + if (!route) return chainThunder(); + // 画布 + if (!core.dymCanvas.chain) core.createCanvas('chain', 0, 0, 480, 480, 65); + else core.clearMap('chain'); + var style = core.dymCanvas.chain; + style.shadowBlur = 3; + style.shadowColor = 'rgba(255, 255, 255, 1)'; + style.filter = 'blur(2px)'; + // 当然还是setInterval + var frame = 0, + now = 0; + var animate = window.setInterval(() => { + if (now >= route.length - 1) { + clearInterval(animate); + setTimeout(() => { + core.deleteCanvas('chain'); + }, 1000); + return; + } + frame++; + if (frame % 2 != 0) return; + core.drawLine( + 'chain', + route[now][0], + route[now][1], + route[now + 1][0], + route[now + 1][1], + '#ffffff', + 3 + ); + // 节点 + if (now == 0) { + core.fillCircle('chain', route[0][0], route[0][1], 7, '#ffffff'); + } + if ( + (route[now + 1][0] - 16) % 32 == 0 && + (route[now + 1][1] - 16) % 32 == 0 + ) { + core.fillCircle( + 'chain', + route[now + 1][0], + route[now + 1][1], + 7, + '#ffffff' + ); + } + // 判断伤害 + lineDamage( + route[now][0], + route[now][1], + route[now + 1][0], + route[now + 1][1], + 4000 + ); + now++; + }, 20); +} +// 链状闪电 获得闪电路径 +function getChainRoute(locs) { + // 照样用setInterval + var now = 0, + routes = []; + var route = window.setInterval(() => { + var nx = locs[now][0] * 32 + 16, + ny = locs[now][1] * 32 + 16; + var tx = locs[now + 1][0] * 32 + 16, + ty = locs[now + 1][1] * 32 + 16; + var dx = tx - nx, + dy = ty - ny; + var angle = Math.atan(dy / dx); + if (dy < 0 && dx < 0) angle += Math.PI; + if (dx < 0 && dy > 0) angle += Math.PI; + // 循环 + 随机 + var times = 0; + while (true) { + times++; + nx += Math.random() * 50 * Math.cos(angle); + ny += Math.random() * 50 * Math.sin(angle); + routes.push([nx, ny]); + if (Math.sqrt(Math.pow(ny - ty, 2) + Math.pow(nx - tx, 2)) <= 100) { + routes.push([tx, ty]); + break; + } + if (times >= 20) { + clearInterval(route); + routes = null; + return; + } + } + now++; + if (now >= locs.length - 1) { + clearInterval(route); + chainAnimate(routes); + } + }, 2); +} +// 随机轰炸 +function randomBoom() { + // 停止轰炸 + if (!flags.booming) { + clearInterval(flags.boom); + return; + } + // 根据阶段数 分攻击速率 和范围 + var boomTime; + var range; + if (hp > 2000) { + boomTime = 500; + range = 11; + } else if (hp > 1000) { + boomTime = 400; + range = 9; + } else { + boomTime = 300; + range = 7; + } + // setInterval + flags.boom = window.setInterval(() => { + var nx = Math.floor(Math.random() * range) + (15 - range) / 2, + ny = Math.floor(Math.random() * range) + (15 - range) / 2; + boomLocs.push([nx, ny, 0]); + if (!flags.booming) clearInterval(flags.boom); + }, boomTime); + // 动画要在这里调用 + boomingAnimate(); +} +// 随机轰炸 动画 +function boomingAnimate() { + // 直接setInterval + if (!core.dymCanvas.boom) core.createCanvas('boom', 0, 0, 480, 480, 65); + else core.clearMap('boom'); + var boomAnimate = window.setInterval(() => { + if (boomLocs.length == 0) return; + if (!flags.booming && boomLocs.length == 0) { + clearInterval(boomAnimate); + return; + } + core.clearMap('boom'); + boomLocs.forEach((loc, index) => { + loc[2]++; + var x = loc[0] * 32 + 16, + y = loc[1] * 32 + 16; + if (loc[2] >= 20) { + var alpha = 1, + radius = 12; + } else { + var radius = 0.12 * Math.pow(20 - loc[2], 2) + 12, + alpha = Math.max(1, 2 - loc[2] * 0.1); + } + var angle = (loc[2] * Math.PI) / 50; + // 开始绘制 + core.fillCircle('boom', x, y, 3, [255, 50, 50, alpha]); + core.strokeCircle('boom', x, y, radius, [255, 50, 50, alpha], 2); + // 旋转的线 + core.drawLine( + 'boom', + x + radius * Math.cos(angle), + y + radius * Math.sin(angle), + x + (radius + 15) * Math.cos(angle), + y + (radius + 15) * Math.sin(angle), + [255, 50, 50, alpha], + 1 + ); + angle += Math.PI; + core.drawLine( + 'boom', + x + radius * Math.cos(angle), + y + radius * Math.sin(angle), + x + (radius + 15) * Math.cos(angle), + y + (radius + 15) * Math.sin(angle), + [255, 50, 50, alpha], + 1 + ); + // 炸弹 下落 + if (loc[2] > 70) { + var h = + y - (20 * (85 - loc[2]) + 2.8 * Math.pow(85 - loc[2], 2)); + core.drawImage('boom', 'boom.png', x - 18, h - 80, 36, 80); + } + if (loc[2] == 85) { + core.drawAnimate('explosion1', (x - 16) / 32, (y - 16) / 32); + boomLocs.splice(index, 1); + if (boomLocs.length == 0) core.deleteCanvas('boom'); + // 伤害判定 + var hx = core.status.hero.loc.x, + hy = core.status.hero.loc.y; + if (loc[0] == hx && loc[1] == hy) { + core.status.hero.hp -= 3000; + core.addPop(x * 32 + 16, y * 32 + 16, -3000); + core.updateStatusBar(); + if (core.status.hero.hp < 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + clearInterval(boomAnimate); + flags.booming = false; + return; + } + } + } + }); + }, 20); +} +// 直线型伤害判定 +function lineDamage(x1, y1, x2, y2, damage) { + // 获得勇士坐标 + var x = core.status.hero.loc.x, + y = core.status.hero.loc.y; + // 是否可能碰到勇士 + if ( + (x1 < x * 32 - 12 && x2 < x * 32 - 12) || + (x1 > x * 32 + 12 && x2 > x * 32 + 12) || + (y1 < y * 32 - 16 && y2 < y * 32 - 16) || + (y1 > y * 32 + 16 && y2 > y * 32 + 16) + ) + return; + // 对角线的端点是否在直线异侧 勇士视为24 * 32 + for (var time = 1; time <= 2; time++) { + // 左下右上 + if (time == 1) { + var loc1 = [x * 32 - 12, y * 32 + 16], + loc2 = [x * 32 + 12, y * 32 - 16]; + // 直线方程 y == (y2 - y1) / (x2 - x1) * (x - x1) + y1 + var n1 = ((y2 - y1) / (x2 - x1)) * (loc1[0] - x1) + y1 - loc1[1], + n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1]; + if (n1 * n2 <= 0) { + core.status.hero.hp -= damage; + core.addPop(x * 32 + 16, y * 32 + 16, -damage); + core.updateStatusBar(); + core.playSound('electron.mp3'); + if (core.status.hero.hp < 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + return; + } + return; + } + } else { + // 左上右下 + var loc1 = [x * 32 - 12, y * 32 - 16], + loc2 = [x * 32 + 12, y * 32 + 16]; + // 直线方程 y == (y2 - y1) / (x2 - x1) * (x - x1) + y1 + var n1 = ((y2 - y1) / (x2 - x1)) * (loc1[0] - x1) + y1 - loc1[1], + n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1]; + if (n1 * n2 <= 0) { + core.status.hero.hp -= damage; + core.addPop(x * 32 + 16, y * 32 + 16, -damage); + core.updateStatusBar(); + core.playSound('electron.mp3'); + if (core.status.hero.hp < 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + return; + } + return; + } + } + } +} - core.plugin.towerBoss = { - initTowerBoss, - autoFixRouteBoss - }; -})(); +core.plugin.towerBoss = { + initTowerBoss, + autoFixRouteBoss +}; diff --git a/public/project/plugin/ui.js b/public/project/plugin/ui.js index ed5c2b1..8bdcf55 100644 --- a/public/project/plugin/ui.js +++ b/public/project/plugin/ui.js @@ -1,5 +1,5 @@ /// -'use strict'; +export {}; (function () { if (main.replayChecking) return (core.plugin.gameUi = {}); diff --git a/public/project/plugin/utils.js b/public/project/plugin/utils.js index f05e37e..f1f7f03 100644 --- a/public/project/plugin/utils.js +++ b/public/project/plugin/utils.js @@ -1,56 +1,53 @@ /// -'use strict'; -(function () { - /** - * 滑动数组 - * @param {any[]} arr - * @param {number} delta - */ - function slide(arr, delta) { - if (delta === 0) return arr; - delta %= arr.length; - if (delta > 0) { - arr.unshift(...arr.splice(arr.length - delta, delta)); - return arr; - } - if (delta < 0) { - arr.push(...arr.splice(0, -delta)); - return arr; - } +/** + * 滑动数组 + * @param {any[]} arr + * @param {number} delta + */ +export function slide(arr, delta) { + if (delta === 0) return arr; + delta %= arr.length; + if (delta > 0) { + arr.unshift(...arr.splice(arr.length - delta, delta)); + return arr; } - - function backDir(dir) { - return { - up: 'down', - down: 'up', - left: 'right', - right: 'left' - }[dir]; + if (delta < 0) { + arr.push(...arr.splice(0, -delta)); + return arr; } +} - function has(v) { - return v !== null && v !== void 0; - } +export function backDir(dir) { + return { + up: 'down', + down: 'up', + left: 'right', + right: 'left' + }[dir]; +} - function maxGameScale(n = 0) { - const index = core.domStyle.availableScale.indexOf(core.domStyle.scale); - core.control.setDisplayScale( - core.domStyle.availableScale.length - 1 - index - n +export function has(v) { + return v !== null && v !== void 0; +} + +export function maxGameScale(n = 0) { + const index = core.domStyle.availableScale.indexOf(core.domStyle.scale); + core.control.setDisplayScale( + core.domStyle.availableScale.length - 1 - index - n + ); + if (!core.isPlaying() && core.flags.enableHDCanvas) { + core.domStyle.ratio = Math.max( + window.devicePixelRatio || 1, + core.domStyle.scale ); - if (!core.isPlaying() && core.flags.enableHDCanvas) { - core.domStyle.ratio = Math.max( - window.devicePixelRatio || 1, - core.domStyle.scale - ); - core.resize(); - } + core.resize(); } +} - core.plugin.utils = { - slide, - backDir, - has, - maxGameScale - }; -})(); +core.plugin.utils = { + slide, + backDir, + has, + maxGameScale +}; diff --git a/script/compress.ts b/script/build.ts similarity index 76% rename from script/compress.ts rename to script/build.ts index 4205415..4104431 100644 --- a/script/compress.ts +++ b/script/build.ts @@ -2,8 +2,8 @@ import fs from 'fs/promises'; import fss from 'fs'; import fse from 'fs-extra'; import Fontmin from 'fontmin'; -import { exec } from 'child_process'; import * as babel from '@babel/core'; +import * as rollup from 'rollup'; (async function () { // 1. 去除未使用的文件 @@ -40,7 +40,7 @@ import * as babel from '@babel/core'; }) ); await fse.remove('./dist/maps/'); - // 编辑器需要留着吗? + // 在线查看什么都看不到,这编辑器难道还需要留着吗? } catch {} // 2. 压缩字体 @@ -98,22 +98,23 @@ import * as babel from '@babel/core'; // 3. 压缩js插件 try { - exec( - `babel ${data.main.plugin - .map(v => `./dist/project/plugin/${v}.js`) - .join(' ')} --out-file ./dist/project/plugin.m.js` - ).on('close', async () => { - const main = await fs.readFile('./dist/main.js', 'utf-8'); - await fs.writeFile( - './dist/main.js', - main.replace( - /this.pluginUseCompress\s*=\s*false\;/, - 'this.pluginUseCompress = true;' - ) - ); - await fse.remove('./dist/project/plugin/'); + const build = await rollup.rollup({ + input: 'public/project/plugin/index.js' }); - } catch { + const code = await build.generate({ + format: 'iife', + name: 'CorePlugin' + }); + const compressed = babel.transformSync(code.output[0].code)?.code!; + await fs.writeFile('./dist/project/plugin.m.js', compressed, 'utf-8'); + + const main = await fs.readFile('./dist/main.js', 'utf-8'); + main.replace( + /this.pluginUseCompress\s*=\s*false\;/, + 'this.pluginUseCompress = true;' + ); + await fse.remove('./dist/project/plugin/'); + } catch (e) { console.log('压缩插件失败'); } @@ -124,20 +125,8 @@ import * as babel from '@babel/core'; const endIndex = main.indexOf('// >>>> body end'); const nonCompress = main.slice(0, endIndex); const needCompress = main.slice(endIndex + 17); - await fs.writeFile('./dist/temp.js', needCompress, 'utf-8'); - await fs.rm('./dist/main.js'); - exec('babel ./dist/temp.js --out-file ./dist/main.js').on( - 'close', - async () => { - const nowMain = await fs.readFile('./dist/main.js', 'utf-8'); - await fs.writeFile( - './dist/main.js', - nonCompress + nowMain, - 'utf-8' - ); - await fs.rm('./dist/temp.js'); - } - ); + const compressed = babel.transformSync(needCompress)?.code; + await fs.writeFile('./dist/main.js', nonCompress + compressed, 'utf-8'); } catch { console.log('main.js压缩失败'); } diff --git a/src/plugin/settings.ts b/src/plugin/settings.ts index 147207e..6fe57f9 100644 --- a/src/plugin/settings.ts +++ b/src/plugin/settings.ts @@ -1,5 +1,7 @@ import { ref, watch } from 'vue'; +// todo 优化,可以考虑改成reactive + /** 打开和关闭ui时是否展示动画 */ export const transition = ref(false); diff --git a/src/plugin/shadow/gameShadow.ts b/src/plugin/shadow/gameShadow.ts index ad8b21c..7c56cab 100644 --- a/src/plugin/shadow/gameShadow.ts +++ b/src/plugin/shadow/gameShadow.ts @@ -1,7 +1,8 @@ -import { power } from 'mutate-animate'; +import { hyper, power } from 'mutate-animate'; import { Polygon } from './polygon'; import { Light, + animateLight, getAllLights, moveLight, refreshLight, @@ -27,7 +28,7 @@ export default function init() { } }; - return { updateShadow, clearShadowCache, setCalShadow, testLight: test }; + return { updateShadow, clearShadowCache, setCalShadow }; } const shadowInfo: Partial> = { @@ -35,11 +36,10 @@ const shadowInfo: Partial> = { { id: 'mt48_1', x: 0, - y: 0, + y: 48, decay: 0, r: 300, - color: '#0000', - followHero: true + color: '#0000' } ] }; @@ -153,7 +153,3 @@ export function setCalShadow(n: boolean) { calMapShadow = n; updateShadow(); } - -function test() { - moveLight('mt48_1', 480, 48, 2000, power(4, 'in-out')); -}