mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-19 17:16:08 +08:00
fix
This commit is contained in:
parent
6ce86501f1
commit
84620ce779
3
components.d.ts
vendored
3
components.d.ts
vendored
@ -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']
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
// 缩略图:事件
|
||||
|
@ -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(
|
||||
|
@ -1,85 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>人类:开天辟地 缩略图集</title>
|
||||
<style>
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: black;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#map-group {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#map-group span {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: aqua;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s linear;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: aquamarine;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 90%;
|
||||
border: 1px solid #ddd4;
|
||||
border-style: dashed;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.map-one {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="map-group">
|
||||
<span>人类:开天辟地 缩略图集</span>
|
||||
</div>
|
||||
<script>
|
||||
const list = ['草原', '洞穴', '勇气之路', '智慧小径', '冰封雪原', '冰封高原'];
|
||||
let html = '';
|
||||
list.forEach(v => {
|
||||
html += `
|
||||
<div class="map-one">
|
||||
<a href="${v}.png" class="map-a" target="_blank">${v}</a>
|
||||
<img src="${v}.png" class="map-img" onclick="window.open('${v}.png')"></img>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
const div = document.getElementById('map-group');
|
||||
div.innerHTML += html;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
Before Width: | Height: | Size: 5.7 MiB |
Binary file not shown.
Before Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
Before Width: | Height: | Size: 3.0 MiB |
Binary file not shown.
Before Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
Before Width: | Height: | Size: 6.9 MiB |
@ -1,8 +1,8 @@
|
||||
main.floors.empty=
|
||||
{
|
||||
"floorId": "empty",
|
||||
"title": "空地图",
|
||||
"name": "空地图",
|
||||
"title": "空地图(不能删)",
|
||||
"name": "空地图(不能删)",
|
||||
"width": 15,
|
||||
"height": 15,
|
||||
"canFlyTo": false,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
250
script/build.ts
250
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<string, string[]> };
|
||||
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<string, string[]> };
|
||||
// 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<string>(`./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<string>(`./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) {
|
||||
|
25
script/buildDeclaration.ts
Normal file
25
script/buildDeclaration.ts
Normal file
@ -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();
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -104,3 +104,6 @@ Mota.register('module', 'UITools', {
|
||||
statusBar: statusBarTools,
|
||||
toolbox: toolboxTools
|
||||
});
|
||||
|
||||
main.renderLoaded = true;
|
||||
Mota.require('var', 'hook').emit('renderLoaded');
|
||||
|
@ -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);
|
||||
|
@ -131,8 +131,8 @@ class GameListener extends EventEmitter<ListenerEvent> {
|
||||
|
||||
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)
|
||||
];
|
||||
};
|
||||
|
||||
|
@ -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');
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
@ -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<Record<FloorIds, LocArr[]>> = {
|
||||
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
|
||||
);
|
||||
}
|
@ -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<Record<FloorIds, LocArr[]>>;
|
||||
|
||||
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.`);
|
||||
}
|
@ -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<number, FloorIds[]> = {
|
||||
1: ['MT0', 'tower7']
|
||||
};
|
||||
const achis: Record<number, Record<AchievementType, number[]>> = {
|
||||
1: {
|
||||
normal: [0, 1],
|
||||
challenge: [0],
|
||||
explore: [1]
|
||||
}
|
||||
};
|
||||
|
||||
export const achiDict: Record<number, number> = {
|
||||
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<Partial<Record<FloorIds, boolean>>>(
|
||||
'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<Partial<Record<FloorIds, boolean>>>(
|
||||
'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]);
|
||||
}
|
||||
});
|
||||
}
|
@ -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<number>('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();
|
||||
});
|
@ -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<DiredLoc> = {};
|
||||
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<Block> = { 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;
|
||||
};
|
||||
}
|
@ -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 };
|
||||
}
|
||||
}
|
@ -1,304 +0,0 @@
|
||||
let levels: number[] = [];
|
||||
|
||||
/**
|
||||
* @type {Record<Chapter, Skill[]>}
|
||||
*/
|
||||
export const skills: Record<Chapter, Skill[]> = {
|
||||
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: [
|
||||
'<span style="color: gold">主动技能,快捷键1</span>,',
|
||||
'开启后会在战斗时会额外增加一定量的攻击,但同时减少一定量的防御。'
|
||||
],
|
||||
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: [
|
||||
'<span style="color: #dd4">第一章终极技能</span>,战斗时智慧的 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: [
|
||||
'<span style="color: gold">主动技能,快捷键3</span>,',
|
||||
'减少一定的攻击,增加一定的防御'
|
||||
],
|
||||
consume: '1000 * level ** 2 + 1000',
|
||||
front: [[9, 5]],
|
||||
loc: [2, 5],
|
||||
max: 5,
|
||||
effect: ['增加${level * 10}%的防御,减少${level * 10}%的攻击']
|
||||
},
|
||||
{
|
||||
index: 11,
|
||||
title: '学习',
|
||||
desc: [
|
||||
'<span style="color: gold">主动技能</span>,可以消耗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: [
|
||||
'<span style="color: #dd4">第二章终极技能</span>,',
|
||||
'每打一个怪物,勇士在本楼层对怪物造成的伤害便增加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 ?? [];
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
// 负责勇士技能:学习
|
||||
const values: Record<number, string[]> = {
|
||||
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--;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
// @ts-nocheck
|
@ -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<AchievementType, boolean[]>;
|
||||
|
||||
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<AchievementData>(
|
||||
'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<AchievementData>('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);
|
||||
}
|
||||
}
|
5
src/types/core.d.ts
vendored
5
src/types/core.d.ts
vendored
@ -1145,6 +1145,11 @@ interface Main extends MainData {
|
||||
*/
|
||||
readonly replayChecking: boolean;
|
||||
|
||||
/**
|
||||
* 渲染进程是否加载完毕
|
||||
*/
|
||||
renderLoaded: boolean;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* 就是core,应该没人会用main.core吧(
|
||||
|
@ -54,7 +54,7 @@
|
||||
<div class="info-editor" v-if="!!selectedItem">
|
||||
<div class="editor-custom">
|
||||
<component
|
||||
:is="selectedItem.controller"
|
||||
:is="(selectedItem.controller as any)"
|
||||
:item="selectedItem"
|
||||
:displayer="displayer"
|
||||
:setting="setting"
|
||||
|
34
tsconfig.declaration.json
Normal file
34
tsconfig.declaration.json
Normal file
@ -0,0 +1,34 @@
|
||||
// packages/vlib-ui/tsconfig.declaration.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@ui/*": ["src/ui/*"]
|
||||
},
|
||||
"outDir": "dist/types/",
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"mota.config.ts"
|
||||
],
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"exclude": ["node_modules", "**/__tests__/**", "**/__demos__/**", "**/*.md"]
|
||||
}
|
@ -21,7 +21,7 @@ export default defineConfig({
|
||||
}),
|
||||
components({ resolvers: [AntDesignVueResolver()] })
|
||||
],
|
||||
base: `/games/${motaConfig.name}/`,
|
||||
base: `./`,
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, './src'),
|
||||
|
Loading…
Reference in New Issue
Block a user