diff --git a/components.d.ts b/components.d.ts index ef69510..cbf48be 100644 --- a/components.d.ts +++ b/components.d.ts @@ -10,15 +10,12 @@ declare module '@vue/runtime-core' { AButton: typeof import('ant-design-vue/es')['Button'] ADivider: typeof import('ant-design-vue/es')['Divider'] AInput: typeof import('ant-design-vue/es')['Input'] - AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] - AProgress: typeof import('ant-design-vue/es')['Progress'] ASelect: typeof import('ant-design-vue/es')['Select'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASlider: typeof import('ant-design-vue/es')['Slider'] ASwitch: typeof import('ant-design-vue/es')['Switch'] Box: typeof import('./src/components/box.vue')['default'] BoxAnimate: typeof import('./src/components/boxAnimate.vue')['default'] - Changable: typeof import('./src/components/changable.vue')['default'] Colomn: typeof import('./src/components/colomn.vue')['default'] EnemyOne: typeof import('./src/components/enemyOne.vue')['default'] Scroll: typeof import('./src/components/scroll.vue')['default'] diff --git a/package.json b/package.json index 387dce7..464023e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "update": "ts-node-esm script/update.ts", "declare": "ts-node-esm script/declare.ts", "type": "vue-tsc --noEmit", - "lines": "ts-node-esm script/lines.ts" + "lines": "ts-node-esm script/lines.ts", + "declaration": "vue-tsc -p tsconfig.declaration.json" }, "dependencies": { "@ant-design/icons-vue": "^6.1.0", diff --git a/public/libs/core.js b/public/libs/core.js index 3096aa9..236013a 100644 --- a/public/libs/core.js +++ b/public/libs/core.js @@ -339,11 +339,15 @@ core.prototype._loadPluginSync = function () { core.prototype._loadGameProcess = async function () { // 加载游戏进程代码 - if (main.pluginUseCompress) { + if (main.pluginUseCompress && main.replayChecking) { await main.loadScript(`project/processG.min.js?v=${main.version}`); } else { if (main.mode === 'editor') { - await main.loadScript(`src/game/index.esm.ts`, true); + if (main.pluginUseCompress) { + await main.loadScript(`project/processG.min.js`); + } else { + await main.loadScript(`src/game/index.esm.ts`, true); + } } } }; diff --git a/public/libs/loader.js b/public/libs/loader.js index 812e43d..4a47318 100644 --- a/public/libs/loader.js +++ b/public/libs/loader.js @@ -525,6 +525,11 @@ loader.prototype.loadOneMusic = function (name) { music.loop = 'loop'; core.material.bgms[name] = music; } else { + if (!main.renderLoaded) { + Mota.require('var', 'hook').once('renderLoaded', () => { + Mota.require('var', 'bgm').add(`bgms.${name}`, music); + }); + } Mota.require('var', 'bgm').add(`bgms.${name}`, music); } }; @@ -538,8 +543,15 @@ loader.prototype.loadOneSound = function (name) { if (main.mode === 'editor') { core.loader._loadOneSound_decodeData(name, data); } else { - const sound = Mota.require('var', 'sound'); - sound.add(`sounds.${name}`, data); + if (!main.renderLoaded) { + Mota.require('var', 'hook').once('renderLoaded', () => { + const sound = Mota.require('var', 'sound'); + sound.add(`sounds.${name}`, data); + }); + } else { + const sound = Mota.require('var', 'sound'); + sound.add(`sounds.${name}`, data); + } } }, function (e) { diff --git a/public/libs/maps.js b/public/libs/maps.js index ffc38a7..a6c45c6 100644 --- a/public/libs/maps.js +++ b/public/libs/maps.js @@ -2588,11 +2588,13 @@ maps.prototype._drawThumbnail_realDrawTempCanvas = function ( blocks, options ) { - const setting = Mota.require('var', 'mainSetting'); - options.ctx.imageSmoothingEnabled = !setting.getValue( - 'screen.antiAliasing', - true - ); + Mota.r(() => { + const setting = Mota.require('var', 'mainSetting'); + options.ctx.imageSmoothingEnabled = !setting.getValue( + 'screen.antiAliasing', + true + ); + }); // 缩略图:背景 this.drawBg(floorId, options); // 缩略图:事件 diff --git a/public/main.js b/public/main.js index 7b1f400..8415057 100644 --- a/public/main.js +++ b/public/main.js @@ -354,8 +354,9 @@ main.prototype.loadAsync = async function (mode, callback) { main.dom.mainTips.style.display = 'none'; } else { await new Promise(res => { + const all = main.pluginUseCompress ? '' : '/all/'; main.loadScript( - `/all/__all_floors__.js?v=${ + `/${all}__all_floors__.js?v=${ main.version }&id=${main.floorIds.join(',')}` ).then( diff --git a/public/maps/index.html b/public/maps/index.html deleted file mode 100644 index b80010c..0000000 --- a/public/maps/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - 人类:开天辟地 缩略图集 - - - - -
- 人类:开天辟地 缩略图集 -
- - - - \ No newline at end of file diff --git a/public/maps/冰封雪原.png b/public/maps/冰封雪原.png deleted file mode 100644 index 5ea0ed4..0000000 Binary files a/public/maps/冰封雪原.png and /dev/null differ diff --git a/public/maps/冰封高原.png b/public/maps/冰封高原.png deleted file mode 100644 index 7c28d78..0000000 Binary files a/public/maps/冰封高原.png and /dev/null differ diff --git a/public/maps/勇气之路.png b/public/maps/勇气之路.png deleted file mode 100644 index 71adeb4..0000000 Binary files a/public/maps/勇气之路.png and /dev/null differ diff --git a/public/maps/智慧小径.png b/public/maps/智慧小径.png deleted file mode 100644 index bb687d9..0000000 Binary files a/public/maps/智慧小径.png and /dev/null differ diff --git a/public/maps/洞穴.png b/public/maps/洞穴.png deleted file mode 100644 index 0f8a0e8..0000000 Binary files a/public/maps/洞穴.png and /dev/null differ diff --git a/public/maps/草原.png b/public/maps/草原.png deleted file mode 100644 index 7d013e9..0000000 Binary files a/public/maps/草原.png and /dev/null differ diff --git a/public/project/floors/empty.js b/public/project/floors/empty.js index 95fad01..23d6a8b 100644 --- a/public/project/floors/empty.js +++ b/public/project/floors/empty.js @@ -1,8 +1,8 @@ main.floors.empty= { "floorId": "empty", - "title": "空地图", - "name": "空地图", + "title": "空地图(不能删)", + "name": "空地图(不能删)", "width": 15, "height": 15, "canFlyTo": false, diff --git a/public/project/functions.js b/public/project/functions.js index 5865e54..7d5d586 100644 --- a/public/project/functions.js +++ b/public/project/functions.js @@ -187,8 +187,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { core.visitFloor(floorId); } } - if (!flags.debug && !main.replayChecking) - Mota.Plugin.require('completion_r').checkVisitedFloor(); }, flyTo: function (toId, callback) { // 楼层传送器的使用,从当前楼层飞往toId diff --git a/public/project/plugins.js b/public/project/plugins.js index 5b53240..07decc7 100644 --- a/public/project/plugins.js +++ b/public/project/plugins.js @@ -991,7 +991,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = { const e = this.col.list.find(v => { return v.x === x + dx * 2 && v.y === y + dy * 2; }); - if (e) { + if (e && e.info.special.includes(16)) { const loc = `${x + dx},${y + dy}`; this.setMapDamage(damage, loc, dam, '夹击'); caledBetween.add(loc); diff --git a/public/swap/2.easy.h5save b/public/swap/2.easy.h5save deleted file mode 100644 index bddf0a7..0000000 --- a/public/swap/2.easy.h5save +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/public/swap/2.hard.h5save b/public/swap/2.hard.h5save deleted file mode 100644 index 011813b..0000000 --- a/public/swap/2.hard.h5save +++ /dev/null @@ -1 +0,0 @@ -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= \ No newline at end of file diff --git a/script/build.ts b/script/build.ts index 996f844..0d67c39 100644 --- a/script/build.ts +++ b/script/build.ts @@ -13,130 +13,132 @@ import compressing from 'compressing'; const type = process.argv[2]; const map = false; -const resorce = type !== 'dev'; +const resorce = false; const compress = type === 'dist'; (async function () { const timestamp = Date.now(); // 1. 去除未使用的文件 - const data = (() => { - const data = fss.readFileSync('./public/project/data.js', 'utf-8'); - const json = JSON.parse( - data - .split(/(\n|\r\n)/) - .slice(1) - .join('\n') - ); - return json; - })() as { main: Record }; - const main = data.main; + // const data = (() => { + // const data = fss.readFileSync('./public/project/data.js', 'utf-8'); + // const json = JSON.parse( + // data + // .split(/(\n|\r\n)/) + // .slice(1) + // .join('\n') + // ); + // return json; + // })() as { main: Record }; + // const main = data.main; + // try { + // const data = [ + // ['./dist/project/floors', '.js', 'floorIds'], + // ['./dist/project/bgms', '', 'bgms'], + // ['./dist/project/sounds', '', 'sounds'], + // ['./dist/project/images', '', 'images'], + // ['./dist/project/animates', '.animate', 'animates'], + // ['./dist/project/tilesets', '', 'tilesets'], + // ['./dist/project/fonts', '.ttf', 'fonts'] + // ]; + // await Promise.all( + // data.map(async v => { + // const all = await fs.readdir(`${v[0]}`); + // const data = main[v[2]].map(vv => vv + v[1]); + // all.forEach(async vv => { + // if (!data.includes(vv)) { + // await fs.rm(`${v[0]}/${vv}`); + // } + // }); + // }) + // ); + // if (!map) await fs.remove('./dist/maps/'); + // // 在线查看什么都看不到,这编辑器难道还需要留着吗? + // await fs.remove('./dist/_server'); + // await fs.remove('./dist/editor.html'); + // await fs.remove('./dist/server.cjs'); + + // await fs.remove('./dist/project/materials/airwall.png'); + // await fs.remove('./dist/project/materials/ground.png'); + // await fs.remove('./dist/project/materials/icons_old.png'); + // } catch (e) { + // console.log('去除未使用的文件失败!'); + // console.log(e); + // } + + // // 2. 压缩字体 + // try { + // // 获取要压缩的文字列表,libs & projects下的所有js文件 + // let texts = ``; + // const exclude = `\n \t`; + // const libs = await fs.readdir('./public/libs'); + // const project = await fs.readdir('./public/project'); + // const floors = await fs.readdir('./public/project/floors'); + // const assets = await fs.readdir('./dist/assets/'); + // const all = [ + // ...libs.map(v => `./public/libs/${v}`), + // ...project.map(v => `./public/project/${v}`), + // ...floors.map(v => `./public/project/floors/${v}`), + // ...assets.map(v => `./dist/assets/${v}`) + // ]; + // for await (const dir of all) { + // const stat = await fs.stat(dir); + // if (!stat.isFile()) continue; + // if (dir.endsWith('.ttf')) continue; + // const file = await fs.readFile(dir, 'utf-8'); + // for (let i = 0; i < file.length; i++) { + // const char = file[i]; + // if (!texts.includes(char) && !exclude.includes(char)) + // texts += char; + // } + // } + + // // 获取所有字体(直接压缩字体会报错 + // const fonts = main.fonts; + // await Promise.all([ + // ...fonts.map(v => + // (async () => { + // const fontmin = new Fontmin(); + // fontmin + // .src(`./public/project/fonts/${v}.ttf`) + // .dest('./dist/project/fonts') + // .use( + // Fontmin.glyph({ + // text: texts + // }) + // ); + // await new Promise(res => { + // fontmin.run(err => { + // if (err) throw err; + // res(''); + // }); + // }); + // })() + // ) + // ]); + // await Promise.all([ + // ...fonts.map(v => { + // return fs.rename( + // `./dist/project/fonts/${v}.ttf`, + // `./dist/project/fonts/${v}-${timestamp}.ttf` + // ); + // }) + // ]); + // } catch (e) { + // console.log('字体压缩失败'); + // console.log(e); + // } + + // 3. 压缩游戏进程 try { - const data = [ - ['./dist/project/floors', '.js', 'floorIds'], - ['./dist/project/bgms', '', 'bgms'], - ['./dist/project/sounds', '', 'sounds'], - ['./dist/project/images', '', 'images'], - ['./dist/project/animates', '.animate', 'animates'], - ['./dist/project/tilesets', '', 'tilesets'], - ['./dist/project/fonts', '.ttf', 'fonts'] - ]; - await Promise.all( - data.map(async v => { - const all = await fs.readdir(`${v[0]}`); - const data = main[v[2]].map(vv => vv + v[1]); - all.forEach(async vv => { - if (!data.includes(vv)) { - await fs.rm(`${v[0]}/${vv}`); - } - }); - }) - ); - if (!map) await fs.remove('./dist/maps/'); - // 在线查看什么都看不到,这编辑器难道还需要留着吗? - await fs.remove('./dist/_server'); - await fs.remove('./dist/editor.html'); - await fs.remove('./dist/server.cjs'); - - await fs.remove('./dist/project/materials/airwall.png'); - await fs.remove('./dist/project/materials/ground.png'); - await fs.remove('./dist/project/materials/icons_old.png'); - } catch (e) { - console.log('去除未使用的文件失败!'); - console.log(e); - } - - // 2. 压缩字体 - try { - // 获取要压缩的文字列表,libs & projects下的所有js文件 - let texts = ``; - const exclude = `\n \t`; - const libs = await fs.readdir('./public/libs'); - const project = await fs.readdir('./public/project'); - const floors = await fs.readdir('./public/project/floors'); - const assets = await fs.readdir('./dist/assets/'); - const all = [ - ...libs.map(v => `./public/libs/${v}`), - ...project.map(v => `./public/project/${v}`), - ...floors.map(v => `./public/project/floors/${v}`), - ...assets.map(v => `./dist/assets/${v}`) - ]; - for await (const dir of all) { - const stat = await fs.stat(dir); - if (!stat.isFile()) continue; - if (dir.endsWith('.ttf')) continue; - const file = await fs.readFile(dir, 'utf-8'); - for (let i = 0; i < file.length; i++) { - const char = file[i]; - if (!texts.includes(char) && !exclude.includes(char)) - texts += char; - } - } - - // 获取所有字体(直接压缩字体会报错 - const fonts = main.fonts; - await Promise.all([ - ...fonts.map(v => - (async () => { - const fontmin = new Fontmin(); - fontmin - .src(`./public/project/fonts/${v}.ttf`) - .dest('./dist/project/fonts') - .use( - Fontmin.glyph({ - text: texts - }) - ); - await new Promise(res => { - fontmin.run(err => { - if (err) throw err; - res(''); - }); - }); - })() - ) - ]); - await Promise.all([ - ...fonts.map(v => { - return fs.rename( - `./dist/project/fonts/${v}.ttf`, - `./dist/project/fonts/${v}-${timestamp}.ttf` - ); - }) - ]); - } catch (e) { - console.log('字体压缩失败'); - console.log(e); - } - - // 3. 压缩js插件 - try { - await fs.remove('./dist/project/plugin.min.js'); + await fs.remove('./dist/project/processG.min.js'); const build = await rollup.rollup({ - input: 'src/plugin/game/index.js', + input: 'src/game/index.ts', plugins: [ typescript({ - sourceMap: false + sourceMap: false, + declaration: true, + declarationDir: './dist/types/' }), rollupBabel({ // todo: 是否需要添加 polyfill? @@ -151,7 +153,7 @@ const compress = type === 'dist'; await build.write({ format: 'iife', name: 'CorePlugin', - file: './dist/project/plugin.min.js' + file: './dist/project/processG.min.js' }); await fs.remove('./dist/project/plugin/'); @@ -181,17 +183,17 @@ const compress = type === 'dist'; } // 5. 杂项 - try { - await fs.copy('./LICENSE', './dist/LICENSE'); - } catch (e) { - console.log('添加杂项失败'); - console.log(e); - } + // try { + // await fs.copy('./LICENSE', './dist/LICENSE'); + // } catch (e) { + // console.log('添加杂项失败'); + // console.log(e); + // } // 6. 资源分离 - if (resorce) { - await splitResorce(type); - } + // if (resorce) { + // await splitResorce(type); + // } // 7. 压缩 if (compress) { diff --git a/script/buildDeclaration.ts b/script/buildDeclaration.ts new file mode 100644 index 0000000..d4c8759 --- /dev/null +++ b/script/buildDeclaration.ts @@ -0,0 +1,25 @@ +import typescript from '@rollup/plugin-typescript'; +import fs from 'fs-extra'; +import * as rollup from 'rollup'; +import resolve from '@rollup/plugin-node-resolve'; + +export async function buildDeclaration() { + const build = await rollup.rollup({ + input: './src/core/index.ts', + plugins: [ + typescript({ + sourceMap: false, + declaration: true, + emitDeclarationOnly: true, + outDir: './dist/types/', + noEmit: false, + jsx: 'preserve' + }), + resolve() + ] + }); + build.write({ + file: './dist/types/index.d.ts' + }); +} +buildDeclaration(); diff --git a/script/dev.ts b/script/dev.ts index 364c529..50f3b17 100644 --- a/script/dev.ts +++ b/script/dev.ts @@ -594,7 +594,7 @@ async function ensureConfig() { // 1. 启动vite服务 const vite = await createServer(); await vite.listen(5173); - console.log(`游戏地址:http://localhost:5173/games/${config.name}/`); + console.log(`游戏地址:http://localhost:5173`); // 2. 启动样板http服务 await ensureConfig(); diff --git a/src/core/audio/sound.ts b/src/core/audio/sound.ts index 699692f..7c536c9 100644 --- a/src/core/audio/sound.ts +++ b/src/core/audio/sound.ts @@ -176,6 +176,7 @@ export class SoundController extends ResourceController< */ play(sound: SoundIds, end?: () => void): number { const se = this.get(sound); + if (!se) return -1; const index = se.playSE(); if (!has(index)) return -1; this.seIndex[index] = se; diff --git a/src/core/index.ts b/src/core/index.ts index 30a4981..56a7ca3 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -104,3 +104,6 @@ Mota.register('module', 'UITools', { statusBar: statusBarTools, toolbox: toolboxTools }); + +main.renderLoaded = true; +Mota.require('var', 'hook').emit('renderLoaded'); diff --git a/src/core/plugin.ts b/src/core/plugin.ts index 72857f8..6aa1a6d 100644 --- a/src/core/plugin.ts +++ b/src/core/plugin.ts @@ -20,8 +20,6 @@ import * as shadow from '@/plugin/shadow/shadow'; import * as gameShadow from '@/plugin/shadow/gameShadow'; import * as fly from '@/plugin/ui/fly'; -import * as chase from '@/plugin/chase/chase'; -import * as completion from '@/plugin/completion'; import * as pop from '@/plugin/pop'; import * as frag from '@/plugin/fx/frag'; import * as use from '@/plugin/use'; @@ -32,8 +30,6 @@ import * as shader from './fx/shader'; Mota.Plugin.register('shadow_r', shadow, shadow.init); Mota.Plugin.register('gameShadow_r', gameShadow, gameShadow.init); Mota.Plugin.register('fly_r', fly); -Mota.Plugin.register('chase_r', chase); -Mota.Plugin.register('completion_r', completion); Mota.Plugin.register('pop_r', pop, pop.init); Mota.Plugin.register('frag_r', frag, frag.init); Mota.Plugin.register('use_r', use); diff --git a/src/game/game.ts b/src/game/game.ts index 842e68b..165840f 100644 --- a/src/game/game.ts +++ b/src/game/game.ts @@ -131,8 +131,8 @@ class GameListener extends EventEmitter { const getBlockLoc = (px: number, py: number, size: number) => { return [ - Math.floor(((px * 32) / size - core.bigmap.offsetX) / 32), - Math.floor(((py * 32) / size - core.bigmap.offsetY) / 32) + Math.floor(((px * 32) / size + core.bigmap.offsetX) / 32), + Math.floor(((py * 32) / size + core.bigmap.offsetY) / 32) ]; }; diff --git a/src/game/system.ts b/src/game/system.ts index 228b289..01e82a2 100644 --- a/src/game/system.ts +++ b/src/game/system.ts @@ -144,12 +144,10 @@ interface PluginInterface { // utils: typeof import('../plugin/utils'); // status: typeof import('../plugin/ui/statusBar'); fly_r: typeof import('../plugin/ui/fly'); - chase_r: typeof import('../plugin/chase/chase'); // webglUtils: typeof import('../plugin/webgl/utils'); shadow_r: typeof import('../plugin/shadow/shadow'); gameShadow_r: typeof import('../plugin/shadow/gameShadow'); // achievement: typeof import('../plugin/ui/achievement'); - completion_r: typeof import('../plugin/completion'); // path: typeof import('../plugin/fx/path'); gameCanvas_r: typeof import('../plugin/fx/gameCanvas'); // noise: typeof import('../plugin/fx/noise'); diff --git a/src/plugin/chase/chase.ts b/src/plugin/chase/chase.ts deleted file mode 100644 index 26b0e59..0000000 --- a/src/plugin/chase/chase.ts +++ /dev/null @@ -1,256 +0,0 @@ -import { Animation, circle, hyper, sleep, TimingFn } from 'mutate-animate'; -import { completeAchievement } from '../ui/achievement'; -import { has } from '../utils'; -import { ChaseCameraData, ChasePath, getChaseDataByIndex } from './data'; - -// todo: 优化,可以继承自EventEmitter - -export function shake2(power: number, timing: TimingFn): TimingFn { - let r = 0; - return t => { - r += Math.PI / 2; - return Math.sin(r) * power * timing(t); - }; -} - -export class Chase { - /** - * 动画实例 - */ - ani: Animation = new Animation(); - - /** - * 追逐战的路径 - */ - path: ChasePath; - - /** - * 是否展示路径 - */ - showPath: boolean = false; - - endFn?: (lose: boolean) => void; - - /** - * 开始一个追逐战 - * @param index 追逐战索引 - * @param path 追逐战的路线 - * @param fn 开始时执行的函数 - */ - constructor( - path: ChasePath, - fns: ((chase: Chase) => void)[], - camera: ChaseCameraData[], - showPath: boolean = false - ) { - this.path = path; - flags.__lockViewport__ = true; - flags.onChase = true; - flags.chaseTime = { - [core.status.floorId]: Date.now() - }; - this.ani - .absolute() - .time(0) - .move(core.bigmap.offsetX / 32, core.bigmap.offsetY / 32); - fns.forEach(v => v(this)); - const added: FloorIds[] = []; - const ctx = core.createCanvas('chasePath', 0, 0, 0, 0, 35); - - for (const [id, x, y, start, time, mode, path] of camera) { - if (!added.includes(id)) { - this.on( - id, - 0, - () => { - flags.__lockViewport__ = false; - core.drawHero(); - flags.__lockViewport__ = true; - this.ani - .time(0) - .move( - core.bigmap.offsetX / 32, - core.bigmap.offsetY / 32 - ); - }, - true - ); - added.push(id); - } - if (!has(path)) { - this.on(id, start, () => { - this.ani.time(time).mode(mode).move(x, y); - }); - } else { - this.on(id, start, () => { - this.ani.time(time).mode(mode).moveAs(path); - }); - } - } - - this.ani.ticker.add(() => { - if (!flags.floorChanging) { - core.setViewport(this.ani.x * 32, this.ani.y * 32); - core.relocateCanvas(ctx, -this.ani.x * 32, -this.ani.y * 32); - } - }); - - if (showPath) { - for (const [id, p] of Object.entries(path) as [ - FloorIds, - LocArr[] - ][]) { - this.on(id, 0, () => { - const floor = core.status.maps[id]; - core.resizeCanvas(ctx, floor.width * 32, floor.height * 32); - ctx.beginPath(); - ctx.moveTo(p[0][0] * 32 + 16, p[1][1] * 32 + 24); - ctx.lineJoin = 'round'; - ctx.lineWidth = 4; - ctx.strokeStyle = 'cyan'; - ctx.globalAlpha = 0.3; - p.forEach((v, i, a) => { - if (i === 0) return; - const [x, y] = v; - ctx.lineTo(x * 32 + 16, y * 32 + 24); - }); - ctx.stroke(); - }); - } - } - } - - /** - * 在追逐战的某个时刻执行函数 - * @param floorId 楼层id - * @param time 该楼层中经过的时间 - * @param fn 执行的函数 - */ - on( - floorId: FloorIds, - time: number, - fn: (chase: Chase) => void, - first: boolean = false - ) { - const func = () => { - if (!flags.chaseTime?.[floorId]) return; - if ( - Date.now() - (flags.chaseTime?.[floorId] ?? Date.now()) >= - time - ) { - fn(this); - this.ani.ticker.remove(func); - } - }; - this.ani.ticker.add(func, first); - } - - /** - * 当勇士移动到某个点上时执行函数 - * @param x 横坐标 - * @param y 纵坐标 - * @param floorId 楼层id - * @param fn 执行的函数 - * @param mode 为0时,当传入数组时表示勇士在任意一个位置都执行,否则是每个位置执行一次 - */ - onHeroLoc( - floorId: FloorIds, - fn: (chase: Chase) => void, - x?: number | number[], - y?: number | number[], - mode: 0 | 1 = 0 - ) { - if (mode === 1) { - if (typeof x === 'number') x = [x]; - if (typeof y === 'number') y = [y]; - x!.forEach(v => { - (y as number[]).forEach(vv => { - this.onHeroLoc(floorId, fn, v, vv); - }); - }); - return; - } - const judge = () => { - if (core.status.floorId !== floorId) return false; - if (has(x)) { - if (typeof x === 'number') { - if (core.status.hero.loc.x !== x) return false; - } else { - if (!x.includes(core.status.hero.loc.x)) return false; - } - } - if (has(y)) { - if (typeof y === 'number') { - if (core.status.hero.loc.y !== y) return false; - } else { - if (!y.includes(core.status.hero.loc.y)) return false; - } - } - return true; - }; - const func = () => { - if (judge()) { - fn(this); - try { - this.ani.ticker.remove(func); - } catch {} - } - }; - this.ani.ticker.add(func); - } - - /** - * 设置路径显示状态 - * @param show 是否显示路径 - */ - setPathShowStatus(show: boolean) { - this.showPath = show; - } - - /** - * 当追逐战结束后执行函数 - * @param fn 执行的函数 - */ - onEnd(fn: (lose: boolean) => void) { - this.endFn = fn; - } - - /** - * 结束这个追逐战 - */ - end(lose: boolean = false) { - this.ani.ticker.destroy(); - delete flags.onChase; - delete flags.chase; - delete flags.chaseTime; - delete flags.chaseHard; - delete flags.chaseIndex; - flags.__lockViewport__ = false; - core.deleteCanvas('chasePath'); - if (this.endFn) this.endFn(lose); - } -} - -export async function startChase(index: number) { - const data = getChaseDataByIndex(index); - flags.chaseIndex = index; - flags.onChase = true; - await sleep(20); - const chase = new Chase( - data.path, - data.fns, - data.camera, - flags.chaseHard === 0 - ); - flags.chase = chase; - const hard = flags.chaseHard; - - // 成就 - chase.onEnd(lose => { - if (hard === 1) { - if (index === 1 && !lose) { - completeAchievement('challenge', 0); - } - } - }); -} diff --git a/src/plugin/chase/chase1.ts b/src/plugin/chase/chase1.ts deleted file mode 100644 index bfed89b..0000000 --- a/src/plugin/chase/chase1.ts +++ /dev/null @@ -1,574 +0,0 @@ -import { Animation, bezier, hyper, linear, shake, sleep } from 'mutate-animate'; -import { Chase, shake2 } from './chase'; -import { ChaseCameraData } from './data'; -import { completeAchievement } from '../ui/achievement'; - -const ani = new Animation(); -ani.register('rect', 0); - -export const path1: Partial> = { - MT16: [ - [23, 23], - [0, 23] - ], - MT15: [ - [63, 4], - [61, 4], - [61, 5], - [58, 5], - [58, 8], - [54, 8], - [54, 11], - [51, 11], - [51, 8], - [45, 8], - [45, 4], - [47, 4], - [47, 6], - [51, 6], - [51, 5], - [52, 5], - [52, 3], - [50, 3], - [50, 5], - [48, 5], - [48, 3], - [35, 3], - [35, 5], - [31, 5], - [31, 7], - [34, 7], - [34, 9], - [31, 9], - [31, 11], - [12, 11], - [12, 8], - [1, 8], - [1, 7], - [0, 7] - ], - MT14: [ - [127, 7], - [126, 7], - [126, 8], - [124, 8], - [124, 7], - [115.2, 7], - [115.2, 9.2], - [110.2, 9.2], - [110.2, 11], - [109.8, 11], - [109.8, 8.8], - [111.8, 8.8], - [111.8, 7], - [104, 7], - [104, 3], - [100, 3], - [100, 4], - [98, 4], - [98, 3], - [96, 3], - [96, 6], - [95, 6], - [95, 7], - [88, 7], - [88, 6], - [85, 6], - [85, 8], - [83, 8], - [83, 9], - [81, 9], - [81, 11], - [72, 11], - [72, 5], - [68, 5], - [68, 8], - [67, 8], - [67, 10], - [65, 10], - [65, 11], - [62, 11], - [62, 9], - [60, 9], - [60, 11], - [57, 11], - [57, 9], - [54, 9] - ] -}; - -export const camera1: ChaseCameraData[] = [ - ['MT16', 0, 10, 0, 1600, hyper('sin', 'in')], - ['MT15', 45, 0, 0, 2324, hyper('sin', 'in')], - ['MT15', 40, 0, 2324, 1992, hyper('sin', 'out')], - ['MT15', 41, 0, 5312, 498, hyper('sin', 'in-out')], - ['MT15', 37, 0, 5810, 1660, hyper('sin', 'in')], - ['MT15', 29, 0, 7470, 830, hyper('sin', 'out')], - ['MT15', 25, 0, 11454, 996, hyper('sin', 'in')], - ['MT15', 12, 0, 12450, 996, linear()], - ['MT15', 0, 0, 13446, 1470, hyper('sin', 'out')], - ['MT14', 109, 0, 0, 1328, hyper('sin', 'in')], - ['MT14', 104, 0, 1328, 332, hyper('sin', 'out')], - ['MT14', 92, 0, 5478, 2822, hyper('sin', 'in')], - ['MT14', 84, 0, 8300, 1992, linear()], - ['MT14', 74, 0, 10292, 2988, linear()], - ['MT14', 65, 0, 13280, 2988, linear()], - ['MT14', 58, 0, 16268, 1992, linear()], - ['MT14', 47, 0, 18260, 3320, linear()], - ['MT14', 36, 0, 21580, 3320, linear()], - ['MT14', 0, 0, 24900, 9960, linear()] -]; - -/** - * 追逐战开始前的初始化函数,移除所有血瓶和门等 - */ -export function init1() { - return Mota.Plugin.require('chase_g').chaseInit1(); -} - -export function chaseShake(chase: Chase) { - chase.ani - .mode(shake2(2 / 32, bezier(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), true) - .time(50000) - .shake(1, 0); -} - -export async function wolfMove(chase: Chase) { - core.moveBlock(23, 17, Array(6).fill('down'), 80); - await sleep(550); - core.setBlock(508, 23, 23); -} - -export function judgeFail1(chase: Chase) { - chase.ani.ticker.add(() => { - if (core.status.hero.loc.x > core.bigmap.offsetX / 32 + 17) { - chase.end(true); - ani.time(750).apply('rect', 0); - core.lose('逃跑失败'); - } - }); -} - -export function drawBack(chase: Chase) { - chase.on('MT15', 0, () => { - ani.mode(hyper('sin', 'out')).time(1500).absolute().apply('rect', 64); - const ctx = core.createCanvas('chaseBack', 0, 0, 480, 480, 120); - ctx.fillStyle = '#000'; - const fn = () => { - if (!ctx) ani.ticker.remove(fn); - core.clearMap(ctx); - ctx.fillRect(0, 0, 480, ani.value.rect); - ctx.fillRect(0, 480, 480, -ani.value.rect); - }; - ani.ticker.add(fn); - }); -} - -export function para1(chase: Chase) { - chase.on('MT15', 830, () => { - for (let tx = 53; tx < 58; tx++) { - for (let ty = 3; ty < 8; ty++) { - core.setBlock(336, tx, ty); - } - } - core.drawAnimate('explosion3', 55, 5); - core.drawAnimate('stone', 55, 5); - }); - chase.on('MT15', 1080, () => { - core.setBlock(336, 58, 9); - core.setBlock(336, 59, 9); - core.drawAnimate('explosion1', 58, 9); - core.drawAnimate('explosion1', 59, 9); - }); - chase.on('MT15', 1190, () => { - core.setBlock(336, 53, 8); - core.setBlock(336, 52, 8); - core.drawAnimate('explosion1', 53, 8); - core.drawAnimate('explosion1', 52, 8); - }); - chase.on('MT15', 1580, () => { - core.setBlock(336, 51, 7); - core.drawAnimate('explosion1', 51, 7); - }); - chase.on('MT15', 1830, () => { - core.setBlock(336, 47, 7); - core.setBlock(336, 49, 9); - core.drawAnimate('explosion1', 49, 9); - core.drawAnimate('explosion1', 47, 7); - }); -} - -export function para2(chase: Chase) { - chase.onHeroLoc( - 'MT15', - () => { - core.setBlock(336, 45, 9); - core.drawAnimate('explosion1', 45, 9); - }, - 45, - 8 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.setBlock(336, 44, 6); - core.drawAnimate('explosion1', 44, 6); - }, - 45, - 6 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.setBlock(336, 44, 4); - core.drawAnimate('explosion1', 44, 4); - core.drawAnimate('explosion1', 48, 6); - core.removeBlock(48, 6); - }, - 45, - 4 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.setBlock(336, 41, 4); - core.setBlock(336, 32, 6); - core.drawAnimate('explosion1', 41, 4); - core.drawAnimate('explosion1', 32, 6); - }, - 41, - 3 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.drawAnimate('explosion3', 37, 7); - core.vibrate('vertical', 1000, 25, 10); - for (let tx = 36; tx < 42; tx++) { - for (let ty = 4; ty < 11; ty++) { - core.setBlock(336, tx, ty); - } - } - }, - 35, - 3 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.vibrate('vertical', 10000, 25, 1); - core.removeBlock(34, 8); - core.removeBlock(33, 8); - core.drawAnimate('explosion1', 34, 8); - core.drawAnimate('explosion1', 33, 8); - }, - 31, - 5 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.setBlock(336, 32, 9); - core.drawAnimate('explosion1', 32, 9); - }, - 33, - 7 - ); - chase.onHeroLoc( - 'MT15', - () => { - core.removeBlock(32, 9); - core.drawAnimate('explosion1', 32, 9); - }, - [33, 34, 34], - 9 - ); - for (let x = 19; x < 31; x++) { - const xx = x; - chase.onHeroLoc( - 'MT15', - () => { - core.setBlock(336, xx + 1, 11); - core.drawAnimate('explosion1', xx + 1, 11); - }, - xx, - 11 - ); - } -} - -export function para3(chase: Chase) { - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 126, 6); - core.setBlock(336, 124, 6); - core.setBlock(336, 124, 9); - core.setBlock(336, 126, 9); - core.drawAnimate('explosion1', 126, 6); - core.drawAnimate('explosion1', 124, 6); - core.drawAnimate('explosion1', 124, 9); - core.drawAnimate('explosion1', 126, 9); - }, - 126, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(508, 127, 7); - core.jumpBlock(127, 7, 112, 7, 500, true); - setTimeout(() => { - core.setBlock(509, 112, 7); - }, 520); - core.drawHeroAnimate('amazed'); - core.setBlock(336, 121, 6); - core.setBlock(336, 122, 6); - core.setBlock(336, 120, 8); - core.setBlock(336, 121, 8); - core.setBlock(336, 122, 8); - core.drawAnimate('explosion1', 121, 6); - core.drawAnimate('explosion1', 122, 6); - core.drawAnimate('explosion1', 120, 8); - core.drawAnimate('explosion1', 121, 8); - core.drawAnimate('explosion1', 122, 8); - }, - 123, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 109, 11); - core.removeBlock(112, 8); - core.drawAnimate('explosion1', 109, 11); - core.drawAnimate('explosion1', 112, 8); - core.insertAction([ - { type: 'moveHero', time: 400, steps: ['backward:1'] } - ]); - chase.onHeroLoc( - 'MT14', - () => { - core.jumpBlock(112, 7, 110, 4, 500, true); - core.drawHeroAnimate('amazed'); - setTimeout(() => { - core.setBlock(506, 110, 4); - }, 540); - }, - 112, - 8 - ); - }, - 110, - 10 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 117, 6); - core.setBlock(336, 116, 6); - core.setBlock(336, 115, 6); - core.setBlock(336, 114, 6); - core.setBlock(336, 117, 8); - core.setBlock(336, 116, 8); - core.drawAnimate('explosion1', 117, 6); - core.drawAnimate('explosion1', 116, 6); - core.drawAnimate('explosion1', 115, 6); - core.drawAnimate('explosion1', 114, 6); - core.drawAnimate('explosion1', 116, 8); - core.drawAnimate('explosion1', 117, 8); - }, - 118, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 112, 8); - core.setBlock(336, 113, 7); - core.drawAnimate('explosion1', 112, 8); - core.drawAnimate('explosion1', 113, 7); - }, - 112, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - for (let tx = 111; tx <= 115; tx++) { - core.setBlock(336, tx, 10); - core.drawAnimate('explosion1', tx, 10); - } - core.setBlock(336, 112, 8); - core.drawAnimate('explosion1', 112, 8); - }, - 115, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.jumpBlock(97, 4, 120, -3, 2000); - for (let tx = 109; tx <= 120; tx++) { - for (let ty = 3; ty <= 11; ty++) { - if (ty == 7) continue; - core.setBlock(336, tx, ty); - } - } - core.drawAnimate('explosion2', 119, 7); - core.removeBlock(105, 7); - core.drawAnimate('explosion1', 105, 7); - }, - 110, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 95, 3); - core.setBlock(336, 93, 6); - core.drawAnimate('explosion1', 95, 3); - core.drawAnimate('explosion1', 93, 6); - }, - 97, - 3 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 87, 4); - core.setBlock(336, 88, 5); - core.drawAnimate('explosion1', 87, 4); - core.drawAnimate('explosion1', 88, 5); - }, - 88, - 6 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 84, 6); - core.setBlock(336, 85, 5); - core.setBlock(336, 86, 8); - core.drawAnimate('explosion1', 84, 6); - core.drawAnimate('explosion1', 85, 5); - core.drawAnimate('explosion1', 86, 8); - }, - 86, - 6 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 81, 8); - core.setBlock(336, 82, 11); - core.drawAnimate('explosion1', 81, 8); - core.drawAnimate('explosion1', 82, 11); - }, - 81, - 9 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 73, 8); - core.setBlock(336, 72, 4); - core.drawAnimate('explosion1', 73, 8); - core.drawAnimate('explosion1', 72, 4); - }, - 72, - 11 - ); - chase.onHeroLoc( - 'MT14', - () => { - for (let tx = 74; tx < 86; tx++) { - for (let ty = 3; ty < 12; ty++) { - core.setBlock(336, tx, ty); - } - } - core.drawAnimate('explosion2', 79, 7); - core.vibrate('vertical', 4000, 25, 15); - }, - 71, - 7 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 68, 4); - core.setBlock(336, 67, 6); - core.drawAnimate('explosion1', 68, 4); - core.drawAnimate('explosion1', 67, 6); - }, - 68, - 5 - ); - chase.onHeroLoc( - 'MT14', - () => { - for (let tx = 65; tx <= 72; tx++) { - for (let ty = 3; ty <= 9; ty++) { - core.setBlock(336, tx, ty); - } - } - core.setBlock(336, 72, 10); - core.setBlock(336, 72, 11); - core.drawAnimate('explosion3', 69, 5); - }, - 67, - 10 - ); - chase.onHeroLoc( - 'MT14', - () => { - core.setBlock(336, 63, 9); - core.setBlock(336, 60, 8); - core.setBlock(336, 56, 11); - core.drawAnimate('explosion1', 63, 9); - core.drawAnimate('explosion1', 60, 8); - core.drawAnimate('explosion1', 56, 11); - }, - 64, - 11 - ); - chase.onHeroLoc( - 'MT14', - () => { - for (let tx = 58; tx <= 64; tx++) { - for (let ty = 3; ty <= 11; ty++) { - core.setBlock(336, tx, ty); - } - } - core.drawAnimate('explosion2', 61, 7); - }, - 57, - 9 - ); - for (let x = 21; x < 49; x++) { - chase.onHeroLoc( - 'MT14', - () => { - for (let ty = 3; ty <= 11; ty++) { - core.setBlock(336, x + 4, ty); - core.drawAnimate('explosion1', x + 4, ty); - } - }, - x - ); - } - chase.onHeroLoc( - 'MT14', - async () => { - flags.finishChase1 = true; - Mota.Plugin.require('replay_g').clip('choices:0'); - core.showStatusBar(); - ani.time(750).apply('rect', 0); - chase.end(); - await sleep(750); - ani.ticker.destroy(); - core.deleteCanvas('chaseBack'); - }, - 21 - ); -} diff --git a/src/plugin/chase/data.ts b/src/plugin/chase/data.ts deleted file mode 100644 index 0a79ff5..0000000 --- a/src/plugin/chase/data.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { PathFn, TimingFn } from 'mutate-animate'; -import { Chase } from './chase'; -import { - camera1, - para1, - para2, - para3, - path1, - chaseShake, - wolfMove, - init1, - judgeFail1, - drawBack -} from './chase1'; - -export type ChaseCameraData = [ - floorId: FloorIds, // 楼层 - x: number, // 目标横坐标 - y: number, // 目标纵坐标 - start: number, // 开始时间 - time: number, // 持续时间 - mode: TimingFn, // 渐变函数 - path?: PathFn // 路径函数 -]; - -export type ChasePath = Partial>; - -interface ChaseData { - camera: ChaseCameraData[]; - fns: ((chase: Chase) => void)[]; - path: ChasePath; -} - -export function getChaseDataByIndex(index: number): ChaseData { - if (index === 1) { - init1(); - return { - camera: camera1, - fns: [ - para1, - para2, - para3, - chaseShake, - wolfMove, - drawBack, - judgeFail1 - ], - path: path1 - }; - } - throw new ReferenceError(`Deliver wrong chase index.`); -} diff --git a/src/plugin/completion.ts b/src/plugin/completion.ts deleted file mode 100644 index 12773ea..0000000 --- a/src/plugin/completion.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { - AchievementType, - completeAchievement, - hasCompletedAchievement -} from './ui/achievement'; -import { changeLocalStorage } from './utils'; -import list from '../data/achievement.json'; - -export const floors: Record = { - 1: ['MT0', 'tower7'] -}; -const achis: Record> = { - 1: { - normal: [0, 1], - challenge: [0], - explore: [1] - } -}; - -export const achiDict: Record = { - 1: 0 -}; - -const loading = Mota.require('var', 'loading'); - -loading.once('coreInit', () => { - Object.values(floors).forEach((v, i) => { - const from = core.floorIds.indexOf(v[0]); - const to = core.floorIds.indexOf(v[1]); - const all = core.floorIds.slice(from, to + 1); - floors[i + 1] = all; - }); -}); - -/** - * 检查所有到达过的楼层,用于成就的计算 - */ -export function checkVisitedFloor() { - changeLocalStorage>>( - 'visitedFloor', - data => { - let needUpdate = false; - core.floorIds.forEach(v => { - if (core.hasVisitedFloor(v)) { - data[v] = true; - needUpdate = true; - } - }); - if (needUpdate) { - checkCompletionAchievement(); - } - - return data; - }, - {} - ); -} - -/** - * 获取一个章节的完成度 - * @param num 章节 - */ -export function getChapterCompletion(num: number) { - if (!achis[num]) return 0; - let res = 0; - const all = floors[num]; - const achiNum = Object.values(achis[num]).reduce( - (pre, cur) => pre + cur.length, - 0 - ); - - // 计算到达过的楼层 - let visitedFloor = 0; - const visited = core.getLocalStorage>>( - 'visitedFloor', - {} - ); - all.forEach(v => { - if (visited[v]) visitedFloor++; - }); - const floorRatio = all.length / (all.length + achiNum); - const floorPoint = (floorRatio * visitedFloor) / all.length; - - let completedPoint = 0; - let totalPoint = 0; - - // 计算成就,占比按成就点走 - for (const [type, achi] of Object.entries(achis[num]) as [ - AchievementType, - number[] - ][]) { - achi.forEach(v => { - totalPoint += list[type][v].point; - if (hasCompletedAchievement(type, v)) { - completedPoint += list[type][v].point; - } - }); - } - const achiPoint = (completedPoint / totalPoint) * (1 - floorRatio); - - res = floorPoint + achiPoint; - - return Math.floor(res * 100); -} - -/** - * 检查完成度成就是否完成 - */ -export function checkCompletionAchievement() { - [1].forEach(v => { - if (getChapterCompletion(v) >= 100) { - completeAchievement('explore', achiDict[v]); - } - }); -} diff --git a/src/plugin/game/hook.ts b/src/plugin/game/hook.ts deleted file mode 100644 index 4f78a30..0000000 --- a/src/plugin/game/hook.ts +++ /dev/null @@ -1,63 +0,0 @@ -export {}; - -const potionItems: AllIdsOf<'items'>[] = [ - 'redPotion', - 'bluePotion', - 'yellowPotion', - 'greenPotion', - 'I482', - 'I484', - 'I487', - 'I491' -]; - -const hook = Mota.require('var', 'hook'); - -hook.on('afterGetItem', (itemId, x, y, isGentleClick) => { - // 获得一个道具后触发的事件 - // itemId:获得的道具ID;x和y是该道具所在的坐标 - // isGentleClick:是否是轻按触发的 - if (potionItems.includes(itemId)) core.playSound('回血'); - else core.playSound('获得道具'); - - const todo: any[] = []; - // 检查该点的获得道具后事件。 - if (core.status.floorId == null) return; - const event = core.floors[core.status.floorId].afterGetItem[`${x},${y}`]; - if ( - event && - (event instanceof Array || - !isGentleClick || - !event.disableOnGentleClick) - ) { - core.unshift(todo, event as any[]); - } - if (core.hasFlag('spring')) { - if (!core.hasFlag('springCount')) core.setFlag('springCount', 0); - if (potionItems.includes(itemId)) { - core.addFlag('springCount', 1); - } - if (core.getFlag('springCount', 0) === 50) { - core.setFlag('springCount', 0); - core.status.hero.hpmax += core.getNakedStatus('hpmax') * 0.1; - } - core.updateStatusBar(); - } - - if (todo.length > 0) core.insertAction(todo, x, y); -}); - -hook.on('afterOpenDoor', (doorId, x, y) => { - // 开一个门后触发的事件 - - const todo: any[] = []; - // 检查该点的获得开门后事件。 - if (core.status.floorId == null) return; - const event = core.floors[core.status.floorId].afterOpenDoor[`${x},${y}`]; - if (event) core.unshift(todo, event as any[]); - - if (todo.length > 0) core.insertAction(todo, x, y); - - if (core.status.event.id == null) core.continueAutomaticRoute(); - else core.clearContinueAutomaticRoute(); -}); diff --git a/src/plugin/game/loopMap.ts b/src/plugin/game/loopMap.ts deleted file mode 100644 index ed18317..0000000 --- a/src/plugin/game/loopMap.ts +++ /dev/null @@ -1,256 +0,0 @@ -import { slide } from './utils'; - -const list = ['tower6']; - -/** - * 设置循环地图的偏移量 - * @param offset 横向偏移量 - */ -function setLoopMap(offset: number, floorId: FloorIds) { - const floor = core.status.maps[floorId]; - if (offset < 9) { - moveMap(floor.width - 17, floorId); - } - if (offset > floor.width - 9) { - moveMap(17 - floor.width, floorId); - } -} - -/** - * 当勇士移动时自动设置循环地图 - */ -function autoSetLoopMap(floorId: FloorIds) { - setLoopMap(core.status.hero.loc.x, floorId); -} - -export function checkLoopMap() { - if (isLoopMap(core.status.floorId)) { - autoSetLoopMap(core.status.floorId); - } -} - -/** - * 移动地图 - */ -function moveMap(delta: number, floorId: FloorIds) { - 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: FloorIds) { - return list.includes(floorId); -} - -export function init() { - events.prototype._sys_changeFloor = function ( - data: any, - callback: () => void - ) { - data = data.event.data; - let heroLoc: Partial = {}; - if (isLoopMap(data.floorId)) { - const floor = core.status.maps[data.floorId as FloorIds] as Floor; - 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; - // @ts-ignore - 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: number, - y: number, - callback: () => void - ) { - 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 - }, - void 0, - void 0, - void 0, - 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; - // @ts-ignore - 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: DeepPartial = { event: {}, x: tx, y }; - b.event!.data = c; - b.event!.trigger = 'changeFloor'; - block = b as Block; - } - } - } - - if (block == null) return _executeCallback(); - - // 执行该点的脚本 - 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(); - // @ts-ignore - core.status.automaticRoute.moveDirectly = false; - this.doSystemEvent(trigger, block); - } - return _executeCallback(); - }; - - maps.prototype._getBgFgMapArray = function ( - name: string, - floorId: FloorIds, - noCache: boolean - ) { - floorId = floorId || core.status.floorId; - if (!floorId) return []; - var width = core.floors[floorId].width; - var height = core.floors[floorId].height; - - // @ts-ignore - if (!noCache && core.status[name + 'maps'][floorId]) - // @ts-ignore - return core.status[name + 'maps'][floorId]; - - var arr: number[][] = - main.mode == 'editor' && - // @ts-ignore - !(window.editor && editor.uievent && editor.uievent.isOpen) - ? // @ts-ignore - core.cloneArray(editor[name + 'map']) - : null; - if (arr == null) - // @ts-ignore - 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); - } - // @ts-ignore - (core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach( - // @ts-ignore - function (one) { - arr[one[1]][one[0]] = one[2] || 0; - } - ); - // @ts-ignore - (core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach( - // @ts-ignore - 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++) { - // @ts-ignore - arr[y][x] = arr[y][x].idnum || arr[y][x] || 0; - } - } - } - // @ts-ignore - if (core.status[name + 'maps']) - // @ts-ignore - core.status[name + 'maps'][floorId] = arr; - return arr; - }; -} diff --git a/src/plugin/game/skill.ts b/src/plugin/game/skill.ts deleted file mode 100644 index fd6b232..0000000 --- a/src/plugin/game/skill.ts +++ /dev/null @@ -1,179 +0,0 @@ -// @ts-nocheck - -// 所有的主动技能效果 -var ignoreInJump = { - event: ['X20007', 'X20001', 'X20006', 'X20014', 'X20010', 'X20007'], - bg: [ - 'X20037', - 'X20038', - 'X20039', - 'X20045', - 'X20047', - 'X20053', - 'X20054', - 'X20055', - 'X20067', - 'X20068', - 'X20075', - 'X20076' - ] -}; - -export const jumpIgnoreFloor: FloorIds[] = [ - 'MT31', - 'snowTown', - 'MT36', - 'MT37', - 'MT38', - 'MT39', - 'MT40', - 'MT42', - 'MT43', - 'MT44', - 'MT45', - 'MT46', - 'MT47', - 'MT48', - 'MT49', - 'MT50' -]; -// 跳跃 -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') { - const loc = core.status.hero.loc; - if (loc.x === 77 && loc.y === 5) { - flags.MT14Jump = true; - } - if (flags.jump_MT14 === 2 && !flags.MT14Jump) { - return core.drawTip('该地图还有一个必跳的地方,你还没有跳'); - } - } - 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('你跳死了'); - } - 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 }; - } -} diff --git a/src/plugin/game/skillTree.ts b/src/plugin/game/skillTree.ts deleted file mode 100644 index 9a653a3..0000000 --- a/src/plugin/game/skillTree.ts +++ /dev/null @@ -1,304 +0,0 @@ -let levels: number[] = []; - -/** - * @type {Record} - */ -export const skills: Record = { - 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: [ - '第一章终极技能,战斗时智慧的 1/10 会充当等量护盾。' - ], - 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: '1000 * level ** 2 + 1000', - front: [[9, 5]], - loc: [2, 5], - max: 5, - effect: ['增加${level * 10}%的防御,减少${level * 10}%的攻击'] - }, - { - index: 11, - title: '学习', - desc: [ - '主动技能,可以消耗500智慧学习一个怪物的技能,', - '持续5场战斗,每学习一次消耗的智慧点增加250,每次升级使持续的战斗次数增加3次。更多信息可在学习后在百科全书查看。' - ], - consume: '2500 * 2 ** level + 5000', - 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%'] - } - ] -}; - -export function resetSkillLevel() { - levels = []; -} - -export function getSkillFromIndex(index: number) { - 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: number) { - return (levels[skill] ??= 0); -} - -export function getSkillConsume(skill: number) { - return eval( - getSkillFromIndex(skill)?.consume.replace( - /level(:\d+)?/g, - (str, $1) => { - if ($1) - return `Mota.Plugin.require('skillTree_g').getSkillLevel(${$1})`; - else - return `Mota.Plugin.require('skillTree_g').getSkillLevel(${skill})`; - } - ) ?? '' - ); -} - -export function openTree() { - if (main.replayChecking) return; - Mota.require('var', 'mainUi').open('skillTree'); -} - -/** - * 能否升级某个技能 - */ -export function canUpgrade(skill: number) { - const consume = getSkillConsume(skill); - if (consume > core.status.hero.mdef) return false; - const level = getSkillLevel(skill); - const s = getSkillFromIndex(skill); - if (level === s?.max) return false; - const front = s?.front ?? []; - for (const [skill, level] of front) { - if (getSkillLevel(skill) < level) return false; - } - return true; -} - -/** - * 实际升级效果 - * @param {number} skill - */ -export function upgradeSkill(skill: number) { - 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; -} - -export function saveSkillTree() { - return levels.slice(); -} - -export function loadSkillTree(data: number[]) { - levels = data ?? []; -} diff --git a/src/plugin/game/study.ts b/src/plugin/game/study.ts deleted file mode 100644 index 94798e2..0000000 --- a/src/plugin/game/study.ts +++ /dev/null @@ -1,53 +0,0 @@ -// 负责勇士技能:学习 -const values: Record = { - 1: ['crit'], - 6: ['n'], - 7: ['hungry'], - 8: ['together'], - 10: ['courage'], - 11: ['charge'] -}; - -const cannotStudy = [9, 12, 14, 15, 24]; - -export function canStudySkill(number: number) { - const s = (core.status.hero.special ??= { num: [], last: [] }); - if (Mota.Plugin.require('skillTree_g').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 studySkill(enemy: any, number: number) { - core.status.hero.special ??= { num: [], last: [] }; - const s = core.status.hero.special; -} - -export function forgetStudiedSkill(num: number, i: number) { - 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[num] ?? []; - 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) { - forgetStudiedSkill(1, i); - i--; - } - } -} diff --git a/src/plugin/game/towerBoss.ts b/src/plugin/game/towerBoss.ts deleted file mode 100644 index cebdba0..0000000 --- a/src/plugin/game/towerBoss.ts +++ /dev/null @@ -1,1589 +0,0 @@ -// @ts-nocheck -import { clip } from './replay'; - -// 1000多行,改不动了,原来什么样就什么样吧 - -// 智慧boss -// 变量们 -var stage = 1, - hp = 10000, - seconds = 0, - boomLocs = [], // 随机轰炸 - heroHp; -// 初始化 -export function initTowerBoss() { - stage = 1; - hp = 10000; - seconds = 0; - heroHp = core.status.hero.hp; - dynamicChangeHp(0, 10000, 10000); - core.insertAction([{ type: 'sleep', time: 1000, noSkip: true }]); - setTimeout(bossCore, 1000); -} - -// 血条 -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; - } - 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; - 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.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; - 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)'; - 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, - [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; - clip('choices:0'); - 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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - Mota.Plugin.require('pop_r').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; - } - } - } -} diff --git a/src/plugin/game/ui.ts b/src/plugin/game/ui.ts deleted file mode 100644 index f661792..0000000 --- a/src/plugin/game/ui.ts +++ /dev/null @@ -1 +0,0 @@ -// @ts-nocheck diff --git a/src/plugin/ui/achievement.ts b/src/plugin/ui/achievement.ts deleted file mode 100644 index 51bc9a7..0000000 --- a/src/plugin/ui/achievement.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { ref } from 'vue'; -import list from '../../data/achievement.json'; -import { achiDict, checkCompletionAchievement } from '../completion'; -import { changeLocalStorage, has } from '../utils'; - -type AchievementList = typeof list; -export type AchievementType = keyof AchievementList; - -type AchievementData = Record; - -export interface Achievement { - name: string; - text: string[]; - point: number; - hide?: string; - progress?: string; - percent?: boolean; -} - -export default function init() { - return { completeAchievement, hasCompletedAchievement, addMountSign }; -} - -export const totalPoint = Object.values(list) - .map((v: Achievement[]) => - v.reduce((prev, curr) => { - return curr.point + prev; - }, 0) - ) - .reduce((prev, curr) => prev + curr); - -/** - * 完成一个成就 - * @param type 成就类型 - * @param index 成就索引 - */ -export function completeAchievement(type: AchievementType, index: number) { - if (flags.debug || hasCompletedAchievement(type, index)) return; - changeLocalStorage( - 'achievement', - data => { - data[type][index] = true; - return data; - }, - { - normal: [], - challenge: [], - explore: [] - } - ); - if (type === 'explore' && !Object.values(achiDict).includes(index)) { - checkCompletionAchievement(); - } - Mota.require('var', 'fixedUi').open('completeAchi', { - complete: `${type},${index}` - }); -} - -/** - * 是否完成了某个成就 - * @param type 成就类型 - * @param index 成就索引 - */ -export function hasCompletedAchievement(type: AchievementType, index: number) { - let data = core.getLocalStorage('achievement'); - if (!has(data)) { - const d = { - normal: [], - challenge: [], - explore: [] - }; - data = d; - core.setLocalStorage('achievement', d); - } - return data[type][index] ?? false; -} - -/** - * 获取当前成就点数 - */ -export function getNowPoint() { - let res = 0; - for (const [type, achi] of Object.entries(list)) { - achi.forEach((v, i) => { - if (hasCompletedAchievement(type as AchievementType, i)) { - res += v.point; - } - }); - } - return res; -} - -// ----- 各个成就相关的函数 - -/** - * 山路木牌 - * @param id 木牌id - */ -export function addMountSign(id: number) { - if (flags.debug) return; - if ( - !core.getLocalStorage(`mountSign_${id}`, false) && - !hasCompletedAchievement('explore', 1) - ) { - changeLocalStorage( - 'mountSign', - n => { - if (n + 1 >= 5) { - completeAchievement('explore', 1); - for (const i of [1, 2, 3, 4, 5]) { - core.removeLocalStorage(`mountSign_${i}`); - } - } - return n + 1; - }, - 0 - ); - core.setLocalStorage(`mountSign_${id}`, true); - } -} diff --git a/src/types/core.d.ts b/src/types/core.d.ts index 08555bc..e96bccb 100644 --- a/src/types/core.d.ts +++ b/src/types/core.d.ts @@ -1145,6 +1145,11 @@ interface Main extends MainData { */ readonly replayChecking: boolean; + /** + * 渲染进程是否加载完毕 + */ + renderLoaded: boolean; + /** * @deprecated * 就是core,应该没人会用main.core吧( diff --git a/src/ui/settings.vue b/src/ui/settings.vue index e2cc6dd..c785a7d 100644 --- a/src/ui/settings.vue +++ b/src/ui/settings.vue @@ -54,7 +54,7 @@