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 @@
-N4IgdghgtgpiBcIASBXKEwCEBOMIGsQAaEANxmwGcBLAezARADUKACAJgDoB2TgZk4BGYiAAmEAC4QEoAGYAbWrWwBJUYwCyAFXbCSACwq0ZIaugDmcRIey0uABzDmRGM5KuyI8yjBKRYjID5yoDTmoBdciLypAh8BvboAB7R7LEI7NwADIKCJOj+EInwALTZILnS8ABs6SSShJXpAJwkojCyCBV8JVAtbfAN1aX0MACeCAAs7AMw8fbRFWMArCQwAI4o1HEwYBIIANoglADuyqJ6B/rUMPKnIAC6JNQSMFCUJgDG9JRS26/woCoLBYADgQJQBVVBJAUo3gYMBDUhIAARko6mD5uxEZR8NR5PJhLCSG9bJRfoIAL4kCRKbwmJHyFAwADSIwQSxAwyuikOLJhYxI9mob3w+SsFOWaw2v2A5MpIEUbxMBUEMQ5CCBzWouDeEjoDEQKFmcoUEHM0pAEBQ1IAyji8QgJNhGQ8nlAACIwKS4h1O3wWq20AAytDe7h9zpAAH1Iz4YKJo6DBOkJmMxg1uOzo9gMPHI4nk+xU+n2foINh1PBklHI6XywBhWiKbAJxDYcxIiAACnYgKI1WqggAlCInvEJABBCSO6hIq1WUD2Wg0XX0RhvLZPbAiWiyWQ+HbwAa6iTyKy7HtLXRLAf3ZEQYXmWwoMAVkCHahgbEfhxOEfTA/nr2F5EMBgi3sep6yPQB7sFWo4SFB2ypAMKLXAgnjeH6uoBJW7KnlOFDWvY94fs4hIWmAbhPFoZhWOkcrmIoHbyJO06zk8JirOs9gAHLQGeICAGbWgAWaiIgB/boAMk4iIAxhGALDmIiANHpgAK2iIgBpmYADplqZpJAaXcJBfJIKCUIGrQSJg974I+tDPq+rAiAZEhGVotD2OZD5Pi+jB2VSNKUG5lkea+ADEoihWMIgouWFANk2ezXn2fa3g5RnmdgMXKHswFZb2YFQooyh1qWTikdaEjDKeXn2VcMA6ulW7wIBl6CPFuUgIhB7gMo6DyCAcpQNZPjBoqDVJkQKq3goShpUV5ikehXg+CQ0anhA5BDS2oDaII3BKqC/JqvA3CatqK76iA2DUOY+g7HKW0gn8IDKvtMKjWIWo1adjAXVdN0kFtCIPU9JAwhUx0fXqX2XddvV/To6S7YdwN7WDOoQ4goi0IcDBytShwUASoAFEdB0lKI72o6uBpGj5ePYBUCOCFWfJVmTJ1o/KpkwyAuMUJigOgqqL2qqz4OU+dUO/dzmMUHwCPsjCGpvWzYuQZLPPYOF/OwgMQso59iCq1z6sLAjit8nr7OGkb0vYDtWvEzCxMixTZ1W7KS2Rrg/XkLmewgNo8Ow2c2iYrDsuw+FsMm7D9OwztsMgrDCJB4H/taFkIhbaHacqpn6eRzn0c5/Tt7RqQ1DLnGG053bjoRnd4Z+v9jew5MLdS7TBJ11hNv0/A3c07z7fq7L/e+oPGvDzbJtjxG6u1+Pae6I3crRmTlAQPSVd5g9W127suxJqDSZNIzSxjBqHRENwGrcEd3DH3wMQqqfCz8s1SzNUd23JIIQJHZMZIkxsh/1BpMAcDRT4NA1IIdMY0GjHyBCAiox8FggL4I/b+Cxf4VAAekGIkx+STE/v0MaQJT58GSA0JYQJqhIKICgogaCxpX0Zt/baY12AwPYBQgcnQxqpjGgsU+VQxoqiINAogQJn533gUA9IMD0jJH/lI0GQIaGX24aDbgIiYFAnftwbIkxuD3F2LcW8DcGqHz4AOWCY10hYN/swwQjDGbvx7GIgcb8JHHzSJw0+XCBHv1EdtAxMjf6GKEaDSRkD7F0JoTEPgGpCxMP5AsZ+QIwGZBAukCBp99E5MvMmHJBD0hZO/g0GR38Ki/zGN/C+LDn7ZKTMo++yQFhHUqdfS+MR5gMKWIw5hsi/4xByrg0x5ig4AwPs1AxIDuDP2BEIrBp9BEqgIUQ8+fDf78JVHw3xATf6BKTJ0o57Dkh8AAVQmIDR+TUJyfAogfB35jFsZ/FJsialEDqd80GFRkGIJAUCX+0imHJFwVIqhR0kkgVBhgshYjv5KPsSA3JEjVlIr4BM8CNsCQH2ASUsh39uBOOJfMrxn8Ki6LIc/WJ20ZEGMpQOf5Y1hk30aWQkBzj4WM1RY/GIQJb4xDGIspoEwmFLHSdfbIoLmELGqA0n5Yw/mJPfvk1lLChFqs6dkB+kKxqXM4U005Ei7lLDgVkM5nDzWnzRYapMqLWnX3aew7+lDYVRP6dfep7jeGFJySYogZicW0z7viwQRCykSKfkw0ZfzdXVAWSBdgNyPFfO8b2SJJKGG9P5FSr1V5TUuoDUw2h0aiEpImBqYRbTonsGPl83QoNUySvIdfEVprRkwO8ZMDUIqjrAl1Xwc1w6BEdIEZE+VYjT6RPAd8nhTDJHAn5CS059Sr7YPsRE6osFkgitBsCatDRkgLP5MC6JYxsjphgS4l5FRP51OqCE0azVSnnxTd8wRaZ2kIKYRmBhsTuDiukXctM0amjQOPj/Cdz9Fipo1MeiDgjbkjuiYau+MQMzaLvbUoDDD2HIIIRwmx1Qn5iuap+5tBThHVA6X8hourBEP0w/eqRHb1GgbQ1e0hkDP7pGcc1Y+yqBzKqE72YR9imnHwcQa9+OVhlwMATkpo9aAEVGSfmtIO7Z3Zq4fyToFzxGdGhSkp+2Qn4XOzUkxJ6inmZLsxqJJYrimvKOiKvtfAxWvN+QqvVdS3MqIvn2ttaYFUMaYQo0tP7Rm3MXQM/hHRwWjpQX8iFKDL75twU+yJ6nemSIWdozN46My3wk7QmVdjgUCpSdImV7rpEJLUepqRkT/6tIFcCqRoLBVnvs4Ko6gqEMwtuQhzr0C7m2egZ0wVEi21JmabkvjH6Wnv3watvpR9FH5pOUinR9j6FZAjWInlKp2EwqyJ5sRU6sgCaTVkPDWRj2cKO2fN5z8ezuJyj2A5RzYsqhe50ChHj1noO5ZulUUqIfvycwa0hL90FPZfrB/BAjikRqjRGl9ixalLIjRJiN2bmEFMZrYkBy2UlJkUasoTAT3m+LdZg1lTinGoKgWqz+xOZt/xU7AnJRiUeEJAs8kCEn607pZfWoBV961ENY/WsB/60gK4AeytITROiOeKTYpYNj1dHc6DrlxTzBHPMc2Bp+pGY1P306OjB6uMhPMiZcxJEmMH6diZcnXsjLmOb20k0j9Cknu4Vboede7K2RZFQq/hIq92jux98qViwxWsbTMK2LdSxVlovtkC+e7ZW8+wbR0P2D2lovldkNBkqflvyaNg6vtG8OAkr5uwEoyM3idY8IuvtngQHpUf8o6VRshVAGRRjEDCGnzCaDUv5fiamXwXR0bL4KFh/KWfemfoiUEj6+SgvLQ//24L+Z89luCZ+kIyCeqNGR76RZJUKod98YVAcTZe6++a76JuzXfFdU6My6p6p3z3zso3y3ykJIIDZ/xSJZAwHKLiJIJnoUZIJqINL6JNDAo0J+LAoajAoYE2KqIDb5r/x0KiKZICp9KZI0KMLkK4GxL/w0J6r/y4F7aCp0KTbiKVLVC3LcF4bUJXqiKQIQZ6rpidJ7bQLcH0LQJNIcIOqKK84tIDhKKOq/yZB8ZG4tLSbHJKK2oEFJi7L4KqExr6F8YQpJhr72IhJlJ8pSamHSZ/aNB8a/onxU62r/onLSZlpZAY5sJiLHKMynx7LHYgIqi/zrLHbvwuLsLNZZDbbbQDjbQhGsaxFQYHZ/xhGgpZDE5/yfygJiIqK8rfyTC+KMzPbvYUa8q+K7KqacLbZaacKRJsJnLvYPY9hk4HZcJHKZF6acK2aMz2b/ZurQF7KPywH/Y7LiL/afydCPzioqjKqyZuoNLzFA6PxmEYIwJ24GoO6nag6PwHZJI7KZFB4Gp9FJL7Fupc4TAiah4Rp2J3GwYU6vIgKvK1ILF3FCajoRo8r9oCLbaLAibOLKpjCmKuKLB3L2JiKcIGoCJCKaqyEwIqY7pGJAIbIJRGJPLfJMIMLXxSLG5PI65wrQqObObfK55x6fqJ6/LfIBbfIqaXgK4gTJLq6kbmYXK9K4HUEtZdZSIQbcFXrXKmoSLmrRLTborXxLBAH3zgFSJ0IVZSLPylEXZiKRG5FQbsLcKqFKGoqrbTHTGbGrIiYvG1KwYvIPr1LcLcJ+r/YGo7LPwhIsq3osKUoNrVIwLbZ3YPbXbOLjrNR6Ic6IIVIQIgKI5dKwLHySKwIzqfx6rbQwJ7Z/wDgHadYjIgSjS6BGKlG6BEbJKTDJpGKjoppgKGoprJKXaFg7rv6FhAIdqFhEKLAgQLGFgAINKFgqYeKwRgJ+KwS5kqYEEpoFmokEJJppCbI7rMI9hAJSofYi6XgWE9gAJLJcKXj2ZcIAIzZcIqakI8JGJPY8IEKxY8KXi/o8IAKSI8IqZlpcJGKdZcKJKjSdDma86UKkah6UIXIfo2LmbIo2KJJRo2LQqRZPxwqGpPxm6kbv7PIXIdrPI64LHPImY671pPJ+KUKOYLoYKkYsoYIXJXwYKElwoQobGO76ZTrDrmabrDou6kU64WHDrQpLJJLQrhaeYXJdKebu466/qebMW+5wqdavLkYKqwGXp7riKXr8iXrNocKXp9q87XHfJorPGKV7oo6vJbLNrC6pi57iqpjCpKqKpgYTDvrNp+IirCosrKp7pXzAm/LNoQrKp9r5qPo0m57Zp1LCp4YAmJ657eKLDnwWGLBuZLIXznz2Zpjny/pphuaSJphir/p1LVqNBMKjRoKV6lFoKjJHZoIHocJoLVofrYJpLIryqjLFLyqSpRryoDrC7pKSrwrpI1XVqXZvyV7ipvyjKCJvzV4HoNLYIHp+LYIFV14EHpKV7urpLt516iJr6V7pobp9Jr4HoQpr7Vr5odKN6V6E5JqAi0YWGAgDpLLCJbUDrsodI969LJX/JPqwH/LgriL/J5pG7/KXy841JPqh41Lgofo1J5popVDgoo5VB/V/IyZVA9J5rwodBD4wodAz7ebzAj4drzB5oNnzB/I/I1Lxa9J9IoIDJJq4J5pTr3oj6br3q9LeL3oDLjrqZ5q2bqZ/ID4zbqYX7gpdJUp5r3JUqM1Pr0LqbX5NCGKJqwGGInriKGIroUaGLaIcKGK3y84kqJqh4konofokorpooZAJqYbFIZCSmXZAaSkLFAb3wNJAaC0eIkqC0EELInoxoPyJosoPwnp9IPzaIQoPy3xZqboZiYbeI3wrq2Y3zaIqI3yC3hY6InpdI6Irr3I6LaJwI6LgGC3/p3yC1lo3y6qdY3wCrJVIJykYF5nAoypoq0LKIo60Jnr8aylqIya0K4GGrSIN0YHeb6IyrAaCL6I0ILH6IDYxrqIYEsqZKtJnpTrqIyqbrqICq9jqJqLjrqK4FtrkJ0LhbkLKJdLkJnr3LkJqJwL/wDZSHJUMb8lXqlEMZ3IUYMbRIcIMYIa87HrcGh7HpUIfrHp3Jor9BXrIr9A3LFL9DmpRr9CdKRa3KdLurUIQYsoIJUJXwIJ3KsYILRIQoIIIb5rpi8FXrZrpg3JTrUJUJSrUJmrmoWHUKdJLKQLcZUJdKQJ3K/qQKdIxLuG5K2ovqZCopKmZAyGrZorzZalNJo65LSYybzaKI8r4KYqiO2reZJjv4yOqEdoyOrYNkyPSY/IyOKJgYtJLZIr45lKqE7EOKorZonLGq6lKHg78ZNLeLmF8a+n8aKLE4KJ8YDEKJIpc4KK2pw6NCoqI6NBNIWoOIOOqGZEnxiIvqHZhNhGTE3ZhNQayFZFhOBF5mWohH3GMyKkU7zaeIhHIreGKlo7mGeLsKRYXa5HSOY4qlhEKMRqRHKMRpQZqMRo3qaNnx+FQb44uIJGOkuJhGsLNRhGQ6zJXa5G+l+n5E3pzawIJHhaPaKl/awK5HOGwLsKRlRmIq5GxnbSuo3oJmJmcLJW8qk5k7DG6CHK2K3G7qcLk4U5zok5k65OTDvZo7EL7NFElMpruJfFFlGpFHnYpoBLSOFhk5zGFjvZrKFjvLvHNmcLLFtlXPvLIWMx+JIuakBJ6EppHLGE9gBIhL1pk5fKMysIy61F06+IxGTnWpFG45rm9GWkBJw47n+Lvb3IBEHJFGRkXkNHvKxlpBFHspsIBJeG64Govovm2noL3GULPyULQ48NfkGq5O/kKuyvTHCM2KbHC7rLTE8pPxurnZkayZ8KyPPLStrKwW2lurHKUIUJ6EWYGrGHDoUIhIYLoIEsYLSsbb4UGquKXI7J3aXLQ7XbDp6luq44cWw7THOE8Ww4GkULuGXKYJur8uXIUJeGCUCJjGiUZuwYvaXoPoaGXr1LDGXqGkibV3o71IlMiovLnYiqrLSPaVBJvGmkvLKOpg+owJFgCLA4TD1LHITCrJ6EiovHurfGwaOnKrrqdsWFNMvJ9EXxCYFFBYCJzahYCIzPfrruwZ/YRXrs071KRlxUTrmlCbDKJUTqrJpsHZ54rtYohpDxWKh55k8p9mNl2ZPJ16c3XzC3OrXyjJEEopxLHYSJkPRr2IAuw6o7WpGpXPPbbEMIY10kf4MK57NpD5iUerdk3pCYNrIIRLvxc4FEDGNG6bZJKajtZJFIRkhnyIQKInfzE7bZmGDL84M62n2tBICKLK5TBoTyjwzJnt6t/GcfNSvzul8JKFKFVPAegpwIrXjVC5pk+KynXwp0SIClgeWXQqLJCbzL86EYfuKUi4SqsoZJ6JQI7oubknfIEIOMwdItwcqioJcpOKLIa3Sq/t3Z0qZEpl/zYoTyawzKIuyPSMzuNGrlke5Mjm4UpVgpvvebIWBLz0H2qJsbftiKjEKtXYKkwEgfCmae9LmaMosLzLJLCM7HE6RkxFmEHYnkY6Q7LYY7LHFthGKlFF6IapG78KUL+cdwUAzz4oC7lfErBIiYvJOKUr5IkLWkaEIkZK/zOFmHg48rIXb1PoJ3dJgeU45pPIZKaruqFnmYtnGeyPZL2ZZrxLzqlp/s8mhETorsSJUK6qILNMKm9chx4q7BPayJ0o8MaEhLuFw7vHLE1LYqryRhQTYDrgej4QwAbTg8QAwDUAthmIeyI++wNSlyRiPDPBIAfgSAo+3hvDyCXDbBDR7BaPeoNBE+lj2CbhYh2jyBaC4B0T6SM98wDzcy0TWQHgDCUD6CYzOSNgogFCc8ABWaA9gkYe80QJAEvUAUvliqo8viv6cAMcEuK7c+UUv6sfchQoMpg2wcP6sBIWThvTwkYuvoIAw+PxvNsfMeZyI8gEALQAA8vqJz/SC7x4AtH6Lb5bzbKPChEuJQF3IvCr9LzoKbx7AqPgEwJcIcIuNgATzvBhD4MaI2NyBQL8KjwcE8PYGSJTsTA5BXLqG8OaNSFIEz7RKCOmJ0W/UIP849VWG8CgNgNgDRDhPKqWfepwEFrksoSWLMPAPKuomineFOBVJUDCoMGAKyPAApSANMMPy4vMOyB2JPzAG6NAKaFYI+vgiUIuBXPQNvxYKz0v2ONmKf7v6CICIrN7Fv+TCeCDIaqYOYGAMoDAKVDAAXwgK/gbwZGT7jA7qvAZMA0HdggBawr4KASIHQC/9d46cO2KADgF7B+wCUXYMUCICYDMB1QbAdkFwHZA8BWAwgSQOIHEDTERAnAWQKoE0DSBlAkgRQPwEJQ0BaA2gcwPYHFBGB1AugUwKIEEDuBCUPAVwP4FsC+BAg0QTx3oECDWBPA8QbwMkFMD+BIg2QcoLkHCDBBigsgUoI0FaDyBQaKgTIN0GqCxBQg/QfIN0EGCjBFghgWYPYEsC7BHA0gQQPuDpBbgt0dOPdGQEQBh+uwaoBgNkFSCpBxgngVwMCEBDzBYQvQf4LkHSCrB2g0wdELEH2DIhEg0IZoMiHxCIhCg2ISYM0HJCbBiQrIToJSHhC0hOgwwRUJiGcDbBJQmIaoJkHqDMhxQpwVYOqHRDDBSQxwdYKiFBDyhVQlQT0PCEODLB+QvQa4PcGwITAKAhqH4N6GVCRhagmoQMIWESDuBjQ/oc0I2FtDLBGQrYSEKWGbDahJQsofYKaGnCNBJwjYcEO6HbCWhOwvIXUMGGHCihqw5QWUNyFxC9h6g3YasLCHrDrhRw/Yf2DcGtwCYpQbwagIcGzC7hQwwEWsIOEAiBhiI94bCNRHPCXBBwuEb0NoEoi9hOQrIbiKxEvCChRIx4X8OYEgi+u2AMEdMN8G2DzhcI4IYSKKGIjHB/w1oeYKaG3D8Rzw2IQ0PpG8j7hfIp4ZULOHDCSR6QoYayLeECi2BYo7Qc4IFGsiPh5I9ocKNFF9DuRnQ84RqO5FciYReIrUZyO6FijTB4wieHzC8E+DoRmw0YRqMVGFDeRCom4RKK6H6jbR8ItUaaJaEMjshyotEUyMxHGjXh6IoMS6PDGBivR4ovEfyKjFCihRkY34WiM6EJCExHIwUa6OxEPCUxmYyUdGJWE2DzRVI0eFaMhGOifhwYmEbiP9FQiLhCIskZWMWFqjah9Q8UZcPjHEimxBY9MXKM9FZjHh1wh0d2JbH4jvhUonkR0L9HRjnRrYo0VcPDGpD6x0orofQOZGaiDR5IoserE1iliZhSop0SaOsHrDex/Y1cWGLmHzjUxjYkcaqMZHpj8h1Yw8USLHExjPhQ45YQaOdFnjyxSIjMUeLDGzjxx34nMW6IjEiiJxho/Yc2JZEHiZRW46eFMIhF7joJHokCcBJ9FPjfxV4yCThPfE8ikxoEvUZ8I+HzCpxpEy8VBNPFAS8xc4isRBOwk1j3RsYlUZ2IIlzj3RLE5oZcKYmQSXxBEwcfCPgmhpEJ1o9AcOIwk6jQJHVWsTgLXE3i0R2CI6KSISGyEjoaA1SSuM0EaTtJxKYiYoNMSGDFJnXAdINVMlqSwU5kgcLpJ0kaojJRk/gfZNMR2S/EM44yeiRMmWSyBHCTATZPsHOTA0h8XScXg8kWTQpPk8yRpMsHeTSBHCByS5M9GSSCJNk+ydONCmxSKRtg/yWFIDFuTIpleMydlLSnWSlJ+UgKTZOinzjJJ9ogQapIMkyT5kbk4KaFKylZTSRtUoNE1Kyn8DfJtk+KdVPKlBSnJfiKQSlMkktThppUwqVQJ6muCg0A0jVJgPGnmSjJPUvKW+ISiKS6p0k0YeFM+HbTdByUgqUtMShBpjpKUoyUKIumkCupuU4qVCNMQzSHBK0zyecMemdSzJD0oKRtKOkFT0p1wq6bdIEGtSChf00KXaO+lfTXJRA+adtDqmLTkWIU46U1LWnwzlpBUhYVZNZRwyGpMMkqbhJiFIy6SyQWabsFGldDcZC0j8RsKRl1T3pIU+waDIvHpTexLA9QT1NRlkCjJm7AGRzMxn/SfpJU9kZ0I0mYyUZDUxiSdMCnNT0Zn42saLLxnVT/JtM8mTFQiScyBZ0syGQTJlkZTSZBU1QYzJxl4zDpiMiaXiM2lzSXpsQm6ZUIqlfijZxk5WVlOZkPDjpu05caDJJkLCKpHM46SLI1SYyiBzs02R5PUHBzKZgMjGdGMeltDEp5gu2RDM1lJyUpNknEadI1k8zZBCc92aBMAkQzlZLsryQrIbHJyM5ZspIUNJCmRCKpmc9WRFLumpzrpAs9kQzKtnyj1x7kusShIBkAyfZRQ2ubXMwGbtdpsk/ceRKjkGyG59c6QaYk3Z0ywZScoeU9g5kXjfRXEgUXPLlkHS7pZ0jWccMtmJzCZtctAftKqmAz2pdItAcPK0m6Td5IU6+QOM7nAjbBNc8ufHKnkRz+ZIcwqVdK4Fph+QZ8q+cvONEUy+5fYpgXfMTmRCAZZ8pMbiLem1jIFK8oYb/PPEDDIFMC2saAsFloL8JsgjBQVM3bYKohQC4mQ4OIV0S15JMweb+NekfzC588paZ9Ijm9DIFgC3Qc9NukFyP5gcpud/LdmdjThlcz4elPmkjzxx5wphbgswWwLjRJ8sucVNnnALNh6UgRYvPwVvz1p1C+KbXIpk7SYpd03maXIClRzFpHaBYSlKFH/zUkMQKqS4LcFygnwHERAEyFoAAApcwBoHMDWhqA8QagAAFFXegYccHWGGDsBxwAALTNDjhuAAAcTcWHAVAdYDQOkH8XjgkQsS8cEyAABe44ccCgEODjgAAGq7xWAQAQlKgAAEr6AeI+gJEG4oF6HB9AAABUYgABqAAJoABVHiMMHpAdKAA9IGEsj6B7AbSrpYGDABuhuA1oAAOorA3gGgfAB0sqXDBxwsy60NaHSB1hxwmAMXuZDrAwABlXS9gDxHmAAAxayBEo0C0AJwWgRQK7xUDxB8AhwUQKQFIANBbAH/JkKQGGARLBA/i/AJUsEC0AgQgYAAIrjhXesysXuCrF7+KoA1AMXuOFhWHBBAwweIBADrCu9JwTAQMCoEDDE9KAmQYYG8B2VgAeIdYUgPIDrBFKkQ1oQMFoFmXxBxwAypAJ0AgCBhMADQbwSgCWXDAoAfEKAISoaBugNAgYFAHyutArANAly2FUyBUAaAgQMABoPssoBaBmlEAHiJQFiVtLhg1AfALErAD2BDg1oUgIspWDqqJAlSIEBEtIBMB8AJkdIDkutBMhmlHS2gAsH0DjKmQsSlQDCqRD4AP+bitxekEOARKJA7AGAK724AqAMEsgUQIcESWHL0ghgJEIcFlV1h0gbwLpWMHwA8RaAYwfQPgFmXUBrQmAKAOCtmWlgkQgSt4NkpQCxLMAMAWZW4vYCxKullS+VJUviCVLKl8gMAB0sDCJKUA+S60CoBQBaBy1TAcFdQGaVlrsAXSiJVoEwCPAeIGgZpVABWCCAxelgSpYcAqCu9OlkKpkOYHwBaBAwLEN4G6AGXYB0gYAFYOkBWDyB9AXq/xbMsDBmrMA2Sr/h0qYBIgmACwCJekAGXjhnecfCoGAEBC0B8ADQDpQyCZDjh7ARS7AL6sDD/rxwsSjpekC6W0AkwwSiVeCrcURLDg8QDpcMCQCzLhgTAbDWLyZB2hE1RSw4OYGZ7DBnI1oGAOOHMAdKeIDQTAPgDGAoB8AF0SpbQG4Biq3QdYLpW6EODZLZlYAfxfYGGApLwV6QJgN4PBXcBwV8QQQGBuoCzKpwtAfQMMHwBuhhgYvYMCoHwD/KV1PEa0FD0ODYbqAXS8wCGB1Wh8/IEgfxQsFID4BKAbi0QG4qBA8RsAYAeQOcvSDPhYlEAbBPoG4AaBsAboewACreCurYl/it0F0tQ0kaFg2S+jUgFiU8QsApAMAOOC6WiBslrvZpSoCR5IhuAkqniF0oqCyB0wxkQMMMFoAsB0gboTwNwEqVjBsl5yoEOOEDCZAGgsytpaQDdDZLqAhwYyBEuyXJge1GgN4NwC0DCrrINEFYHWAqAdKJA2/LQFoEKXjhzleS7JeYHHCCALt8gC7TxBQDXQ3QFQPJfIH8WlgsNogfQK73OVvB9A44IENZBk0/aulf2jQJdEwAnaSNmASpdkuwDgrXesSyyG8GaX6BYl5yjpUiH0AaBuA5gS5SxvBW+re16WkUOYDcUQqxg44JgPYBWCPKKg+gJkAMv8URL5AHS0gLYDyX4AUA4KljZQBWUoAkAKwfxbQD4BIhKA44eID9rGDVatAboN1eYDGCmhYljgfxWMFkAqAyV+qinbEvSBuKgwHiusOCp4j+L4gSAcwIIG22Bh7AYwUJd5q376AVglSlAJgDrAm70g5gIEHWCgBQB8A1ofxeYCZ0VANA/a9JGjtd6HAxgtAM1eOAaB1gxg7W2Ja7y6WyAdAKwcPQsAu3jh4NtAJDfEEvXjhsAtSlQEku+3sAulxmmTV4tJDU7ANua+wP4uoBIBDgl6+QKptEDnLlNggAZWAGtAJLBAXSjpXWE6VQrMA5yhHUOoiX+KmAtATABEqYBdKgQjy60OYCgDYAM9yYcdZQA1jjhHNYvOsKEoqBug3QEKlYOwCRAwBaAWgLpYcGaWVLRABWy/REswBjBXe4K4FNQFiXDA3FFQa0C9tGVAgUA5gCoGhutBug4dgYSpVvx/XsBCl+ANXWMDF4VA3gf8LUMktO0aA7t7AWoOCv8V1huAmOrFewAiVq7+Nsqt0IardCVK0dHStxeCrABMBC9TAVLdQDdD+Lzl9gccMMBf2CBqAOuqAK7zF4qBYlfAccKpudUgHMlQIMzUyH8XpBqAmAJEOYC6V1gVgAIJAEUt2XnK3FzBypcvvx0dKYAtOpgLIFiXZLLVdPFAG6HHBuKWAYAcsDxBUBu63FCweIOwHBWxKxe0m7ANaHiBEbNDsyygA4YgAgHZltAUQG6CgBrKVAWgJgMksDANA3FWgDpQsFuWHA9lMAJgEwHB24IJAWgN3REqgDZKmAhwWZeUtoAs7qA+KsYEyGU1aAIlXSqAM0tEB1gKVWgV3qqpY3jgaArvWwGMGtAVA6w8elYNQBo0q7wVmAcwMMCZAVBAwCqvnRoEiBi9ZAKwMANkuBWBhsl3AV3m8CBBuKul6wMjdkqQBMBRAYvDGECA0AqBZAfAa0IcAWCxLrQxqm9SoDGAqAmAKwcFf4fHCRbwVFwYYL9uaWzKFgAIdgLICQAQBDgsgMrdwEDDnLA1GgPgFEqHXYAJDYvMYLPoSPeHDgbS8FWAcCNuh0gRSioJQHkBIhKlsgN0K7xeWzK6w2S9gB31d7yBZARxsAEiD4CHAgQHS8FSoFIAoBSAGgZg3jDdBKAwAfAOsM0tPWkAxg1BqAGLzdBtLzA0x85eCsECBh2AiGhYLIH43DAvVrveIGGsiVYGbD4Kjpe6HsDNKKgHaiJWL0OBvBYl8gSlRAAo36BAwWmq6G7swDQrxwPEKABEpVX+KmQlStxf4v8U8RuDYweIDuHiDeLBASAJEJgFmXYA3FnK/5bIDAARKIAjQUQE9rdBMBMNTANxZEcwDxAxglAJwOOAWBxn4gmAaI/gEw32AIlHoXvcMDdDu7aA/ioo+YH8WKHxwPRjpf4vqX6A+ATAfQJgGaWHBAlfAHiHLv0BvAxe8QStREoWBaAA9dSpkBAFiUSAeI44GAF0o0DgqYT+On7ZUutAmnsl/e+QOOtEB+rXel0WJQ0ASNIAkAogFYG4r/iYBt1hwag1PpSNjBwdzSygEUvkAshmlQa85QsCYDlqKgcZrzR2a93pAYAYvDQG0uyWWR6VGh0rW6EqPjgIAWgNpc0raX6BwVH2iAECGODgqewzB2QG0o0CUA2lS4JAOkFoAvHYlTIak5gFI1dKVAESiJZMGSVJbOzwS6taIHkALBOz5yqJdgFmWVL6zTILvYLrrAKGul6QLQHWfMCo79ARSrpTACKXmQmQhB/AB4q6VuKilboJEPRetCcrAwogFAOwHkDcAOl+gSpZ6bABFLqAsa2dQftj3RHGLYvWJUiHiAEXfdsymACgEqVimdzsypEAMpUDgrrQPERI8+fBWyBY9JOw4EUvOXnLNlTITk4lfHD4AkQSIHiECoqClrhg0+hYFAEODnL/FQIMZcCCKVjAqN1oJAK8nqP4BhgEAbgBMdsAeLZo0xusG6BUDnKBlga9IOsvBUrAmQTICLewFkNVn8AZUcwEkrWUz7O97ASpdgFd7mAxz8JkUEgHBVpRFr41uK4oFiWVKmAEgIpeYCS3sBBd7AFYLMsOCGWddpVniPMoZNuhzlH1ypUiA0A0nrQYvWZeOFkB1hMAgu8FWMHsDfbMASWpAOco0B1gCA1oRsNQHHAaAwNWgJY0CDlMNAJ1dYBYEgFd6kBIb5gdI28GoAoBsl8QLpdaEoBe79A8u60LvuFUaB2AFhqQMMDrAdKVgKxhk2ptiUVB4gfASgAMqrUnhQL2AeIJQDeARKeIom/QMDqgDxAeIHa7gOsuoAsWeltAMXoIDrDUBhg1oBnUwGb2PLMApy6TbEsOCjrvr6V35RoGGA8mgQyht4P4oaNdHsARSiALQECMwBzlEvXfeYfOuu9/FKAanTgH8WYAulMyqAJUvksRL4g4uygP4u1vDAeITILpUqYiV1gVAb+lAEyHhtvBMABuusKOrdCqqIAmAMACttUMqAcb3AIpYrth3UBsl8gCoPgG2NvKNA9geU24vjPxBs744a9ekGCX+Xub6W+FZVcqWzLYNRS3c/gEeUwANAhwM69wCZASBgwjJypZkqZDxBXelSpZQbZe0sb/F7ADQCsFICyBn9BBrQJ7brBuLx1zSrjYNfs1cJul1Ad44IFKVvB0rUSlg10qOD+KBl7V844Br7O367jTwbgKIHMD86/1lWxVRAEvSUBQj9gdIPYD0O97ONXSiAJNbhMwB8AN2q6OWdGPMnml4Kwi6FqRtvBEV2SoS+2oAPDbOd5y6K2jcctWbTV6twvRUHBUD6wA6QZtVABUBtnjgzt13kZrnNuhZoTAKjRIFjPsAPFTAWJXWBF0NGYAryhoIoGaXmb5TD+ywEgHtUnLZAsylAPIHwBKnyj+Ac5XiviAKrzlXpv7SoFC1UOmz8QeQOVvwAV2jgJmkzeYEcCmb2wlADQ4rf8XyB3duSeozQcDDpa6wqd/FfXZWC0AoARS/xb8soARKZwHS9gMMH8VIBsz/OzAIICKVMhRA5WlYOOFBMVA/l6yniNwG2DvrKlboeJ5Uo6Wt2w95getYIHkM8QkE5yhM54cgsQ20lgYDQFAFzsSAUjXSqe2xYFXsHuA6R+IF4ekM1O+T+gFQPYFkDeKIlgN2JfoFkDXHXrogUA8MAkALAIARSyI6cDvgLBgjmAenSgHSDgqGDTAP5f4rcV1h8AbwLo8mo6MBLBAEgSwJQDWCjGmQ6QBkOCvWNgB2APj8O6jfsCVLoTYwX6wi6gD8YGgWF7AEgFoDH74guS7JbQC6VIhuTqlygB+pquzLplTAPgBAEF0VAkAWgIpZkFmUqAzTshtwCoEEBaAHd44agHapRAsailAymAKQH8XjX0ghuslaQbUBvB4gboCJd2f51vAVAEACAN8aZCm37dPETVVko6M8QkQ2AKAAMsBOiA0z2APgF0uaVAh8A+gK7QMqZANBzlKwN0LMoy3nLDg+AZF/g8DCSmYANSjoJUqKUNqGgES8FWdc2UqAlESAetf9oaDEvZAgZhYGTfMAoBWjXTzAEgH8s7rDg4K25a5FIC0AeI3x/QLMoaACa6wlL1pfghDvpANATupAA0HK3oagQniwox0o6VDGgl+AJAKDr6Pg34trZm/ZgFkCzqqrPEGjUyGoCJrYlzxsYIo/ZNQB9A1oCJUyAWADK6wgYcu8UsoAoB077J3O9kogD+q2n5gUQDkb4MNAilUj/qAU7ABQAYllADjQ0DaXTHmlvezJHWGCfKHXe7AZFxkbGD+LKlfWypSO6RBi83FKADKxSaCWVKGgtAVg8SrF6DnhgAyyfTLpWB8BRAgYJ4DxDR2t8nDub/QI0BUBuKxeEgMjTxBlukG/4f2oDM0utAaB5NdYI4+No6VuhED5CDfW4qQD2B7ADq4zYcfeUDLUnogULTAH/NMukQwwZ9SgE3W+6hdjNli5VYqBtKkQHSpB9ofo3AailBJqAHwDcXGnRAsgbgEgB4hvAGgtevo7Mq8UVACj5O0gG0td0I3sAPYWZVAGtCyBDgEgMS1yqPNgBZAo5uF9SbaUoBoAbSwE5UocSKGjg5gV3W8HYA+Kakc2rQH5toD63c7gx1vn/fSDxKTtZ99gFoBoDWhKlrvQVGcsQ2kAeldeioEwBovWgGg/iopdaD4BtKtAQIMXmCreADLEV6QNpTQBlUGqUVx5lALUfMDgqJPu+8Ffdo0BjAoAnZ7JW0qwCaqBlx6rNZQC1szWvAkS8cFoFnXwWazWeqAB0vyXDArd17hYNRqBArrojNSJHkwCZBi8sV+gMrxi9JA93KlKwewNaHOX+HwVxEWgDAFnAVBzAkau47IA0A92X9hKtk9QCBCVKJDOOlYOWfLvnL9AboeWx0vEBQ+zN7AfAM0vSCkBHbj9ygECFP0vqxeD3/QGL212zKq3AKwQFS/jNMhAbfACO39oqCFXRAZTm4//CaP5LVN4x6nfmuycwBComz8HS5+QsnKkAbS2ZUV/+QIGmQ+gM0EyDeAAGTNsy+wNW/HBgBmL94SgLGdb4QA4t2xioNgDRVBW3gcVwpSsDaVvAB7RRzZcYaBC7HALO2lQK71zvB23FlAFQFAE7XmBi7BFiAJUpc3jWUANvwQF76ZBaANARS/AMioJuEnuLkTzJEgEqWbuIllSsADUtmURbxwXtjm/EFEBMg2lUxqTU6Zx3gG19Ftiw28FeV/7Y/7ARyGABqtMgOl5gTazkchfWgt9gS8wEUu4cqB9EWd4b0GfKUQq09KgT03w6yUTrFrFQc5ZUupAKqKgtABVSs9X9kPEzXG8Fc8i78vBNrbxjCwsEnDZWj/hHoVzABgDgqNA5V8FV0oDcb7C9wwUQG2fMADLqAGl7JYHpCX6B+osS2gKQG8VJvKYw6UDfGvzF52AG0zsNclPgBUBgdNky/0hXQj2EMxzCvRqsIAagC/chjQ9UyR6nT1RcMl9cdXMAIARe3BV5ANxVIAvdGJXwB+jDBGwB+baJxUAileIBgBf3fQCztj7LOyOAiNCfzGAUjdgxWAilQVCgAnDR7SrV/TLhEtV5DEA2acxjOsBM9XDNxTAAPzcwD4BwVCRy0B4gMXnsBgjRezaVDgfXTlMf+T313UxgH7RJ1wVNpS5NUrcwHYBZlQuwydd1EnV3VnzSJVhVd1CQHsBTHN4HBUFgXOygBAbYbxxtMAFADrBDgStSZUYDUZRgNFtFYE903gI/28DcXZpU99VnAEBiVwVdM02sNADpU2t9AFADT1ylHIypNylbwOGAsHSww7N8dSI2m83FPgFoBwVHNVoBJvMI2aVQffV2ncIlVoND0+9CAHssr/fAFUcYAQHy6UUTUoyDcZ7ROyQAmXF53MB4fGLSgNXXDGBN82ldgHB1hvcy1XNRAGH3n0SdXvyHtdTcFSFd4lV3iJNIbAVRQABlfjCp9qALh3ndvvRrQm1gQOi2tAtAU63sBVzN0A6VIzGow0AUAel3KU5ArOxyNmnLvyS0hXbl3iAIlW1TcUUVFQAINbVCAAiVJTYVyZAoAc5RQBbVdQK3UsLFYA9U5/IEH2t2ARcDGMJAcFXpcxjGD1Ud4TRywhUwAQiyt1J1EbXMA7vLhzcVqAM5WLdD1QJXrQIlNxTwtBUNq2jtslZVH60mQJgEm9JrDpSQA6jeIAfscVNpSZA1gYO2aU3gewHiAdtMAFmVMlFQAqAYQjwLT1ieFgJgNSQrpT4NPVccG9V31Fe1oRMAaiygB5ALhHsAs7FQBg0pvPNTGA9Aj81jVBAXVXG97AYUIGV4gNxX1d4gRzQkAOlPgHeCLjTwOa0WNUjUOAajNpSaNNnDpTaV7AH/gVVc3N4DcVXed7yyUXPLJXJ1wVSqxhDUQmEPiV31Tk3o0vfIV3sAFgJkCC0IlLv2tBOTCoDF4FtVS2Ig8zQH3XNCDMp0tMoAQQCa93+RdwCde/eQDqCmANpQAsAA0QDGVFrVYPOUIAc5XW0ffGD1McIlRtTGAojQMAs8lw5fTNAhtBcywsoAIVy/su/BkF7Mv7cpSVN5AWJVtVLDfxR3UVADsAGUIlRky/tWgt5xQB1Mew0D8hreN2GBmnS80EAlTDxQwAfTJgCHD8AQQHiAmAdbV7MmQO8JitxwM6yFcJAWoyYBslQ4Bi1FrR6zyVjgXsx5MWjYTTsMwAc5WLs3QNkKtNHzJK310H7GEMcNmLa2zGBzAUgGaV5LBYBo9YlJgH8VW/cwFmVcDQQFgBqAWr2Gd5NHW1kBAwM3T99zlQMFIB/DOG3EBNHeQDu8kQLJQa97DHFVhsVgQMHzMKfJQOqtzAX1SYAqraG2IDXeQQBUByoDQF2NXedqyJcPQfQBXdsAF5TF4tADVxRs3QO9z4AMtOY3kBTw4YGWMJAJgGfBSAQQBQBBdcrXKU93RXQv03QY91mUJzPgH0BTzN4BohqANc3b5LIGFR9Cp9FYAF0JAN5RjtMXESw0M6jUn1b4HdUgHOVLofC0K9FNPbX8VB3WJXMAGIl0LddUQusEqUtAY91dUojaK22AVAa0DqVldHiMwA+tJEHOVmlV3nJ86vJAF9VbLLpVMjkgn0LF5KAI53ksVgWQH2Udow4CecUALDzF4LHewG4BB3DQCxUulDwLcUNzcE0KU6Q7gAgAbowMGhNsAJYzwBLzSfTSs8HIZXJtOTaIzyVRXTxWcgO+F6N1dKlUGxDUJATayBAatMXkqUjPTAAE9YrQVUsNSAUtw0BQNNpQrU6wBoDFNmlXYwkBIjeQAGUxeUDTF54IrpXKgilFAG4BXIiAFq9FVN4xkNQo240T1slcy131g7WdU1VCba0DaVyDFQDaUeIVKyRAlTQMFldIHIZQ6V51FQEKVHNWJViUilP10DUkAbJRDV5AWIPehngdxUoACbAa1iU3QFx0KUeNIoyei9zKdUCM8Y85WWMUAEFXBUJAIECwB8PZyPotFAOflCjptBCFd5MARcBqNRzCmPRCJY2gEfcg1C/zb4wAP+whNaPfAErMIlWp0y9fIskyKUt+K6y0tgXBVyQBILCoArgbfTABg1ADXH0ts+AQr1WAmQMYEo0EtRC3LjfLSAEwBh9dx1VCBlKSzF43ow4DdBSAVezZCwTUjRyNNzWJXx1rQFkyYBnjXCyTUL9Ps2xMIlCWNiUtAYF2oA+TSpX8VslMk2qsyzDnX5icVdvjBMY9L7WaVi3CdQacZo3zWi04lcpRFAONKzR8tsANGx4hwtSFXHB3VccDdBR1JDQu1vNaV2k1qbRvWmUdlMYAkdAwXIKSUNASs3f0RTGDSI82lccHid9A0IN2U2NFbSKjjIWJX6hEvc83VCLbIEFmU5dUdUDALNCJUxgXEfW0NVpzT9QqAYAdgBQBPfYYDPVnPN0DmUfFBYF3VClfawGtwVGo1EAPvdw3GNNfDpUD1hnJcJO08ADyPU1MdHc07MJ/aQ3L5zza0AOd3+LCyPcVgjPQkB8AFYGPAUAOjRYAaAE5yUNftE3yX0oAcwEwBYlZ9XMAz1Rm3KUzjFQDYsZ1fADeVv1NpQGVpESwAkA6PVWzcV/3ccBvdT1H2MwAtAYYEYDXDcFXecKbEeLlMO+K02G9EvT11y9hveoLbCYVKACZACle3RTjOE8kyt02zSgCZBZwccDkdKlAZXcci3JJSJiHnMi3MAeIdbSqVYgz0DLVCTN53SAxeF1yocmQEWP8UIAOjTNBSACoFd8QjDQGtAXEcgH1sL7c8x4gVgAZWYtZlc11EBhtMXj1U3gOwPSBslJrUN1TzHHWm9QdHsAy0eIM5UwAJAVWz6MpI2JULB2DKhOOTRAaG1uNs/cXU2dKAfXRQB1IvgD81rQV3jvj2vCQCQBH4wME0CELYCy6U2lNxRWCGw4yHMB4gWJXNdRdfw1mVkrQwFlMWVKXwH02A5swzUGjBC051SY7AGGBtlTkAuTH1UgHwCBlI7UuB842ZVu82lfAHJSeVKBNG0ulfm1aB8AKbWGBm7XoyBAONc016jFlFOMOBOQV3l+tbAhVzwcxlDAJDj/4wJTkigQdUNoAkVbJWDtKtDQH6Tb/LQEW1Zzc/VJB6TUQFGsmDZlXO9dnOM24AIle3Td0mHbgBod/FNjTGc3Qe5XeNUrKrwWBzjagFP8pgiQA48IlWJRtMIlQLS6V8ABYFcc4VeXw/Nnwew1edGwV3xUAgjFYF1coABoCzjhgQQBANp3c4zitglZkFJBO7JEEDBmDfqHDMVgSpCRBBTNpU5UllWZS6VQbFAGtBBNBoEX0gvI733UKTewDCMWQJGMEBzzFQCZA+DLcwxV7AYFFd5PQZpUK0fYgc3Rcw9ai1CU4jBsKaTtDVNXWUBNb1OGAaE/xQ0B1MIqOoBLgLUF/c2nTAAO8cgl5LRshQA5PJ07NZw1EA+AOmG4B5lAXld4IAc1xgAFgEtXHVi3ZJNd5RAN4EtVUHN4E7jS9G00Q0uHUg16NqAKdTmVMAIEB68OrKAG69ndWYNm0mQIpR7A37ewDcVttXEANtYVJ0CRA7XWlIas3FTACGckAWGPJ9LtJ0Ka0GgUbW4901e4zfgw9CQHSASNCoAmcL4QxFVDgzEYPq1bLccBeS50gZS8B+YtjMvNCwCdQ0BrzOoygSpvBC3Vj31F5L5V1ooiAWBXnMZ3kBHANHSwdwVWjKoTLIoDWwsLAv70oAYA7ZQ6tcMtaGajaAUgxG8cbWQGzCvALUyZc3gAWPOV4gV4PsAFkw6JtjndfAFL1xQ+YB/VSAbrVQisEypVNBWI85W09rQIyGGBsAUmLF4u/GAAcc6wUQBOd2TK3weS3dOzwRsF06eIkA3vRAxrNVEhYGuM2lUC1CidjI73MBIHNiw4CAonIKlSRLMYHOVavcZKysS4+DUGVD9axPkM74Aqwyc5YiuLR9LU2f0QSVgSBxGBObe4wZB01WwGtAOlE1MLBAEqlD2sWw3END9IHLpRnMkQXgO4BgPNOwz0oTWgDUMSLITVIBn/ad0OAVgVoC8MElfECA0lPSw1uVUnIpW68hnZ3gWBmTdtX6zvrTd1EdUPS1UoAKgYiw41gXHk2x1DEpN0qVSAcHWWSeIufWCUklLAzzUvElQDWyTfXk171FTFOIGUKgK3xvTSQWn0+MpIhYArgnQjs1+DaAFUPiAVgXtTvsqNGZMa8sPUgHWUprHjR4g7PFuzUMno87WS0btYJK6VeTSVTPS2XH7ViUV043QzVdTVn3/jYjJHVxjXkzjWhTvvcdScM1zHxQfsxeIpSZSLDbgBbVydYWzdAxeOu2EM8AagEoRmlQq2fcYfeUzC9is5VRcdswWJRZV2TK3SgAI3OsIbUmQJAAjD/9IgO4BmlXqKyj/Q0bTwBE9XUCnV2ADVK3NTveIBziVAUPkyjJrPGx01qAbbUCzHrZpQmscbSgF6VuTbkyoBAssVTJtCk9B3OV1jfWy286wOnih9aAbNNmVDdSgGYDjE98FsiOlC+zAMmAc70bURtGqFkBw7TAFizdVV3imNutTAEQ9egyX2tAbTT3XNUUVcnWyV1MWgAfMdkzAELd49N10+1NfKVyD8FfBoCec2lfg20zZAfAELAP1BoAoD2VTey0BGdYjSizSAPiBSN9AdLGFc/3bAGCckNCoGyd9AGZKBAJACoAkAyXIECZ5yrcHRxs4rCfz4B1nVzV+sYAWV05s2XajLGAkQaREPVXVPPSYA3dN0A89hlGNSq97AO8JW9tLGK3idONS0Byc5kv1xCCiku7QwCpLPkLALPg1s1uNKVJJzaUTgknSBBo7Nb1rsyVeI2V9jI7JVXdTNU1SGdp3RO0DBW3eQGt8b3ZpWCD3DJACCjgNN4Ct0kQewFEdJ3HOPkA0nXzXgtttUlWztCdHxXgtNYuR2ICFgQQLpgkAMXm20+AMAH8TNA8Gx88Y/MkPsA542WzNA9I3TT6NlY/IAEzBlYDTcVAHeJWFivMyLS0ByosNRfjE+b3XIikQJwDPVAwOU2f06zS0HHA2lWJWwAAbCO3P168+XygA6wf7S0B9ABoEOiwNV3jrBGTL1WwAalNlyhVPFEj0EBN07jUOABlMYG0tLHKZLGU9kgAxg8SdUgEA8pNWaBoNojSXVR03FCYDfcHLDNW2AxeLUw1U6kdsFV10gT5LCV5bdXzt0q1ctWDNoUtpXkAGgZTL4ABrIYK3Mwsq/UHCsE6GLA0J/JQLHNGbdPwftsldlwfz6gvJQABeB4pEBSALwEZBzQVwHQAngIiAv8KwJ+AEBfi1UAf4viuMGt56IEgHIAqAdmBYBsADgB4B+AIQBEBE3cd0YAWA0BiBB9PSMHUoIADEqRAVQSMBd5nkSMEEA3gWLP+ZZANfFiyRwGvlhB+aKlF9ZbkH5AOBGeHPlYZsSF9Aik0BMAGMd5AIgE5K8QdgV5LuS8YXJAgAA===
\ 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 @@