diff --git a/public/libs/maps.js b/public/libs/maps.js index 3839ea0..6cdeaaa 100644 --- a/public/libs/maps.js +++ b/public/libs/maps.js @@ -2552,9 +2552,8 @@ maps.prototype._drawThumbnail_realDrawTempCanvas = function ( options ) { // todo: storage获取方式优化 - const storage = mota.storage; - const s = storage.get(storage.fromAuthor('AncTe', 'setting')); - options.ctx.imageSmoothingEnabled = !s.getValue( + const setting = Mota.require('var', 'mainSetting'); + options.ctx.imageSmoothingEnabled = !setting.getValue( 'screen.antiAliasing', true ); @@ -3111,7 +3110,6 @@ maps.prototype.removeBlock = function (x, y, floorId) { const block = blocks[i]; this.removeBlockByIndex(i, floorId); this._removeBlockFromMap(floorId, block); - if (!main.replayChecking) mota.plugin.gameShadow.updateShadow(true); return true; } return false; @@ -3274,7 +3272,6 @@ maps.prototype.setBlock = function (number, x, y, floorId, noredraw) { } } } - if (!main.replayChecking) mota.plugin.gameShadow.updateShadow(true); }; maps.prototype.animateSetBlock = function ( diff --git a/public/libs/ui.js b/public/libs/ui.js index 844b377..4424846 100644 --- a/public/libs/ui.js +++ b/public/libs/ui.js @@ -4228,6 +4228,4 @@ ui.prototype.deleteAllCanvas = function () { this.deleteCanvas(function () { return true; }); - if (main.mode === 'play' && !main.replayChecking && mota.plugin.shadow) - mota.plugin.shadow.initShadowCanvas(); }; diff --git a/public/project/functions.js b/public/project/functions.js index 8907daa..a50de05 100644 --- a/public/project/functions.js +++ b/public/project/functions.js @@ -50,7 +50,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { core.hideStatusBar(core.hasFlag('showToolbox')); else core.showStatusBar(); if (main.mode === 'play' && !main.replayChecking) { - mota.plugin.fly.splitArea(); + Mota.Plugin.require('fly').splitArea(); Mota.require('var', 'hook').emit('reset'); } else { flags.autoSkill ??= true; @@ -143,11 +143,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { // ---------- 重绘新地图;这一步将会设置core.status.floorId ---------- // core.drawMap(floorId); - if (!main.replayChecking) { - mota.plugin.gameShadow.updateShadow(); - mota.plugin.gameCanvas.setCanvasFilterByFloorId(floorId); - } - // 切换楼层BGM if (core.status.maps[floorId].bgm) { var bgm = core.status.maps[floorId].bgm; @@ -206,7 +201,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { } } if (!flags.debug && !main.replayChecking) - mota.plugin.completion.checkVisitedFloor(); + Mota.Plugin.require('completion').checkVisitedFloor(); }, flyTo: function (toId, callback) { // 楼层传送器的使用,从当前楼层飞往toId @@ -345,7 +340,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { if (callback) callback(); if (flags.onChase) { - mota.plugin.fly.startChase(flags.chaseIndex); + Mota.Plugin.require('chase').startChase(flags.chaseIndex); if (flags.chaseIndex === 1) { core.playBgm('escape.mp3', 43.5); } diff --git a/src/core/plugin.ts b/src/core/plugin.ts index 3757fae..3ec5582 100644 --- a/src/core/plugin.ts +++ b/src/core/plugin.ts @@ -17,6 +17,22 @@ // import frag from '@/plugin/fx/frag'; // import { Mota } from '.'; +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 status from '@/plugin/ui/statusBar'; +import * as frag from '@/plugin/fx/frag'; + +Mota.Plugin.register('gameShadow', gameShadow, gameShadow.init); +Mota.Plugin.register('fly', fly); +Mota.Plugin.register('chase', chase); +Mota.Plugin.register('completion', completion); +Mota.Plugin.register('pop', pop, pop.init); +Mota.Plugin.register('status', status); // todo: 改成系统变量,而非插件 +Mota.Plugin.register('frag', frag, frag.init); + // // todo: 将插件更改为注册形式,分为渲染进程和游戏进程两部分,同时分配优先级 // export function resolvePlugin() { diff --git a/src/game/system.ts b/src/game/system.ts index 1353a2f..392ed67 100644 --- a/src/game/system.ts +++ b/src/game/system.ts @@ -99,7 +99,6 @@ interface PluginInterface {} export interface IMota { rewrite: typeof rewrite; - rewriteSys: typeof rewriteSys; Plugin: IPlugin; @@ -279,7 +278,6 @@ class Mota { private static variables: Record = {}; static rewrite = rewrite; - static rewriteSys = rewriteSys; static Plugin = MPlugin; constructor() { @@ -401,53 +399,6 @@ function rewrite, T = O>( } } -type _FI = FunctionInterface[K]; - -/** - * 全量复写系统函数或在系统函数函数前添加内容 - * @param key 系统函数名称 - * @param type 复写类型,full表示全量复写,front表示在原函数之前添加内容 - * @param re 复写函数,类型为full时表示将原函数完全覆盖,为front时表示将该函数添加到原函数之前 - * @param bind 原函数的调用对象,默认为base - * @param rebind 复写函数的调用对象,默认为base - */ -function rewriteSys( - key: K, - type: 'full' | 'front', - re: (this: T, ...params: [..._F<_FI>[0], ...any[]]) => _F<_FI>[1], - bind?: any, - rebind?: T -): (this: T, ...params: [..._F<_FI>[0], ...any[]]) => _F<_FI>[1]; -/** - * 在系统函数后追加内容 - * @param key 系统函数名称 - * @param type 复写类型,add表示在函数后追加 - * @param re 复写函数,类型为add时表示在原函数后面追加复写函数,会在第一个参数中传入原函数的返回值, - * 并要求复写函数必须有返回值,作为复写的最终返回值。 - * @param bind 原函数的调用对象,默认为base - * @param rebind 复写函数的调用对象,默认为base - */ -function rewriteSys( - key: K, - type: 'add', - re: ( - this: T, - ...params: [_F<_FI>[1], ..._F<_FI>[0], ...any[]] - ) => _F<_FI>[1], - bind?: any, - rebind?: T -): (this: T, ...params: [..._F<_FI>[0], ...any[]]) => _F<_FI>[1]; -function rewriteSys( - key: K, - type: RewriteType, - re: (this: T, ...params: [..._F<_FI>[0], ...any[]]) => _F<_FI>[1], - bind?: any, - rebind?: T -): (this: T, ...params: [..._F<_FI>[0], ...any[]]) => _F<_FI>[1] { - // @ts-ignore - return rewrite(Mota.requireAll('fn'), key, type, re, bind, rebind); -} - declare global { interface Window { Mota: IMota; diff --git a/src/plugin/chase/chase.ts b/src/plugin/chase/chase.ts index f9b61e3..26b0e59 100644 --- a/src/plugin/chase/chase.ts +++ b/src/plugin/chase/chase.ts @@ -2,14 +2,9 @@ import { Animation, circle, hyper, sleep, TimingFn } from 'mutate-animate'; import { completeAchievement } from '../ui/achievement'; import { has } from '../utils'; import { ChaseCameraData, ChasePath, getChaseDataByIndex } from './data'; -import { init1 } from './chase1'; // todo: 优化,可以继承自EventEmitter -export default function init() { - return { startChase, chaseInit1: init1 }; -} - export function shake2(power: number, timing: TimingFn): TimingFn { let r = 0; return t => { diff --git a/src/plugin/completion.ts b/src/plugin/completion.ts index 7b1e3a0..00a47a6 100644 --- a/src/plugin/completion.ts +++ b/src/plugin/completion.ts @@ -6,10 +6,6 @@ import { import { changeLocalStorage } from './utils'; import list from '../data/achievement.json'; -export default function init() { - return { getChapterCompletion, checkVisitedFloor }; -} - export const floors: Record = { 1: ['MT0', 'tower7'] }; diff --git a/src/plugin/fx/frag.ts b/src/plugin/fx/frag.ts index 85f034b..cc38c0f 100644 --- a/src/plugin/fx/frag.ts +++ b/src/plugin/fx/frag.ts @@ -1,4 +1,5 @@ import { Animation, linear, sleep } from 'mutate-animate'; +import { has } from '../utils'; interface SplittedImage { canvas: HTMLCanvasElement; @@ -23,15 +24,44 @@ const MAX_ROTATE = 0.5; /** 碎裂动画的速率曲线函数 */ const FRAG_TIMING = linear(); -export default function init() { - return { applyFragWith }; +export function init() { + Mota.rewrite(core.events, 'afterBattle', 'add', (_, enemy, x, y) => { + // 打怪特效 + if (core.getLocalStorage('frag') && has(x) && has(y)) { + const frame = core.status.globalAnimateStatus % 2; + const canvas = document.createElement('canvas'); + canvas.width = 32; + canvas.height = 32; + core.drawIcon(canvas, enemy.id, 0, 0, 32, 32, frame); + const manager = applyFragWith(canvas); + const frag = manager.canvas; + frag.style.imageRendering = 'pixelated'; + frag.style.width = `${frag.width * core.domStyle.scale}px`; + frag.style.height = `${frag.height * core.domStyle.scale}px`; + const left = + (x * 32 + 16 - frag.width / 2 - core.bigmap.offsetX) * + core.domStyle.scale; + const top = + (y * 32 + 16 - frag.height / 2 - core.bigmap.offsetY) * + core.domStyle.scale; + frag.style.left = `${left}px`; + frag.style.top = `${top}px`; + frag.style.zIndex = '45'; + frag.style.position = 'absolute'; + frag.style.filter = 'sepia(20%)brightness(120%)'; + core.dom.gameDraw.appendChild(frag); + manager.onEnd.then(() => { + frag.remove(); + }); + } + }); } export function applyFragWith( canvas: HTMLCanvasElement, length: number = 4, time: number = 1000, - config: any = {} + config: any = {} // todo: 类型标注 ) { // 先切分图片 const imgs = splitCanvas(canvas, length); diff --git a/src/plugin/game/enemy/battle.ts b/src/plugin/game/enemy/battle.ts index 869db76..bf62765 100644 --- a/src/plugin/game/enemy/battle.ts +++ b/src/plugin/game/enemy/battle.ts @@ -167,35 +167,6 @@ core.events.afterBattle = function ( // 如果已有事件正在处理中 if (core.status.event.id == null) core.continueAutomaticRoute(); else core.clearContinueAutomaticRoute(); - - // 打怪特效 - if (core.getLocalStorage('frag') && has(x) && has(y)) { - const frame = core.status.globalAnimateStatus % 2; - const canvas = document.createElement('canvas'); - canvas.width = 32; - canvas.height = 32; - core.drawIcon(canvas, enemy.id, 0, 0, 32, 32, frame); - const manager = mota.plugin.frag.applyFragWith(canvas); - const frag = manager.canvas; - frag.style.imageRendering = 'pixelated'; - frag.style.width = `${frag.width * core.domStyle.scale}px`; - frag.style.height = `${frag.height * core.domStyle.scale}px`; - const left = - (x * 32 + 16 - frag.width / 2 - core.bigmap.offsetX) * - core.domStyle.scale; - const top = - (y * 32 + 16 - frag.height / 2 - core.bigmap.offsetY) * - core.domStyle.scale; - frag.style.left = `${left}px`; - frag.style.top = `${top}px`; - frag.style.zIndex = '45'; - frag.style.position = 'absolute'; - frag.style.filter = 'sepia(20%)brightness(120%)'; - core.dom.gameDraw.appendChild(frag); - manager.onEnd.then(() => { - frag.remove(); - }); - } }; core.events._sys_battle = function (data: Block, callback?: () => void) { diff --git a/src/plugin/game/enemy/checkblock.ts b/src/plugin/game/enemy/checkblock.ts index f17fbc5..48a3c9f 100644 --- a/src/plugin/game/enemy/checkblock.ts +++ b/src/plugin/game/enemy/checkblock.ts @@ -10,7 +10,7 @@ control.prototype.checkBlock = function (forceMockery: boolean = false) { const damage = info?.damage; if (damage) { if (!main.replayChecking) { - mota.plugin.pop.addPop( + Mota.Plugin.require('pop').addPop( (x - core.bigmap.offsetX / 32) * 32 + 12, (y - core.bigmap.offsetY / 32) * 32 + 20, (-damage).toString() diff --git a/src/plugin/game/removeMap.js b/src/plugin/game/removeMap.js index 388a6a8..69f7f10 100644 --- a/src/plugin/game/removeMap.js +++ b/src/plugin/game/removeMap.js @@ -36,7 +36,7 @@ export function removeMaps(fromId, toId, force) { deleted = true; } if (deleted && !main.replayChecking) { - mota.plugin.fly.splitArea(); + Mota.Plugin.require('fly').splitArea(); } } diff --git a/src/plugin/game/towerBoss.js b/src/plugin/game/towerBoss.js index e8cb0cf..07b882f 100644 --- a/src/plugin/game/towerBoss.js +++ b/src/plugin/game/towerBoss.js @@ -496,7 +496,11 @@ function intelligentArrow(fromSelf) { damaged[loc + direction] = true; core.drawHeroAnimate('hand'); core.status.hero.hp -= 1000; - mota.plugin.pop.addPop(x * 32 + 16, y * 32 + 16, -1000); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -1000 + ); core.updateStatusBar(); if (core.status.hero.hp < 0) { clearInterval(skill1); @@ -511,7 +515,11 @@ function intelligentArrow(fromSelf) { damaged[loc + direction] = true; core.drawHeroAnimate('hand'); core.status.hero.hp -= 1000; - mota.plugin.pop.addPop(x * 32 + 16, y * 32 + 16, -1000); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -1000 + ); core.updateStatusBar(); if (core.status.hero.hp < 0) { clearInterval(skill1); @@ -637,7 +645,11 @@ function icyMomentem() { if (x == locs[index][0] && y == locs[index][1]) { core.drawHeroAnimate('hand'); core.status.hero.hp -= 5000; - mota.plugin.pop.addPop(x * 32 + 16, y * 32 + 16, -5000); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -5000 + ); core.updateStatusBar(); if (core.status.hero.hp < 0) { core.status.hero.hp = 0; @@ -812,7 +824,11 @@ function getThunderDamage(x, y, power) { 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.pop.addPop(x * 32 + 16, y * 32 + 16, -3000 * power); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -3000 * power + ); core.updateStatusBar(); if (core.status.hero.hp < 0) { core.status.hero.hp = 0; @@ -976,7 +992,7 @@ function ballThunder() { ) { damaged[i] = true; core.status.hero.hp -= 3000; - mota.plugin.pop.addPop( + Mota.Plugin.require('pop').addPop( x * 32 + 16, y * 32 + 16, -3000 @@ -1486,7 +1502,11 @@ function boomingAnimate() { hy = core.status.hero.loc.y; if (loc[0] == hx && loc[1] == hy) { core.status.hero.hp -= 3000; - mota.plugin.pop.addPop(x * 32 + 16, y * 32 + 16, -3000); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -3000 + ); core.updateStatusBar(); if (core.status.hero.hp < 0) { core.status.hero.hp = 0; @@ -1525,7 +1545,11 @@ function lineDamage(x1, y1, x2, y2, damage) { n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1]; if (n1 * n2 <= 0) { core.status.hero.hp -= damage; - mota.plugin.pop.addPop(x * 32 + 16, y * 32 + 16, -damage); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -damage + ); core.updateStatusBar(); core.playSound('electron.mp3'); if (core.status.hero.hp < 0) { @@ -1545,7 +1569,11 @@ function lineDamage(x1, y1, x2, y2, damage) { n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1]; if (n1 * n2 <= 0) { core.status.hero.hp -= damage; - mota.plugin.pop.addPop(x * 32 + 16, y * 32 + 16, -damage); + Mota.Plugin.require('pop').addPop( + x * 32 + 16, + y * 32 + 16, + -damage + ); core.updateStatusBar(); core.playSound('electron.mp3'); if (core.status.hero.hp < 0) { diff --git a/src/plugin/game/ui.js b/src/plugin/game/ui.js index 180accf..079d91d 100644 --- a/src/plugin/game/ui.js +++ b/src/plugin/game/ui.js @@ -20,8 +20,8 @@ export {}; function updateVueStatusBar() { if (main.replayChecking) return; - mota.plugin.status.statusBarStatus.value = - !mota.plugin.status.statusBarStatus.value; + const status = Mota.Plugin.require('status'); + status.statusBarStatus.value = !status.statusBarStatus.value; } ui.prototype.drawBook = function () { diff --git a/src/plugin/pop.ts b/src/plugin/pop.ts index 9678751..cb5bf1c 100644 --- a/src/plugin/pop.ts +++ b/src/plugin/pop.ts @@ -5,12 +5,8 @@ let pop: any[] = []; let time = 0; -// 插件必须有默认导出,并返回所有外部会用到的函数,所有返回的函数会被转发到core上 -// 并且在这里面完成所有的初始化,函数外部也可以进行初始化,但完全不能涉及到样板相关内容 -export default function init() { +export function init() { core.registerAnimationFrame('pop', true, popValue); - // 返回值是所有外部可见内容 - return { addPop, pop }; } /** @@ -53,7 +49,7 @@ function popValue(t: number) { * @param py 弹出的纵坐标 * @param value 弹出的文字 */ -function addPop(px: number, py: number, value: string) { +export function addPop(px: number, py: number, value: string) { var data = { px: px, py: py, diff --git a/src/plugin/shadow/gameShadow.ts b/src/plugin/shadow/gameShadow.ts index 1638736..4c20101 100644 --- a/src/plugin/shadow/gameShadow.ts +++ b/src/plugin/shadow/gameShadow.ts @@ -1,10 +1,8 @@ -import { hyper, power } from 'mutate-animate'; import { Polygon } from './polygon'; import { Light, - animateLight, getAllLights, - moveLight, + initShadowCanvas, refreshLight, removeAllLights, setBackground, @@ -13,17 +11,11 @@ import { setShadowNodes } from './shadow'; import { pColor } from '../utils'; -import { drawHeroDetail } from '../game/fx/heroDetail'; - -export default function init() { - const origin4 = control.prototype.drawHero; - control.prototype.drawHero = function () { - origin4.apply(core.control, arguments); - drawHeroDetail( - core.status.heroCenter.px - 16, - core.status.heroCenter.py + 20 - ); +import { setCanvasFilterByFloorId } from '../fx/gameCanvas'; +export function init() { + // 勇士身上的光源 + Mota.rewrite(core.control, 'drawHero', 'add', () => { if (core.getFlag('__heroOpacity__') !== 0) { getAllLights().forEach(v => { if (!v.followHero) return; @@ -33,9 +25,25 @@ export default function init() { refreshLight(); }); } - }; - - return { updateShadow, clearShadowCache, setCalShadow }; + }); + // 更新地形数据 + Mota.rewrite(core.maps, 'removeBlock', 'add', success => { + if (success && main.replayChecking) updateShadow(true); + return success; + }); + Mota.rewrite(core.maps, 'setBlock', 'add', () => { + if (main.replayChecking) updateShadow(true); + }); + Mota.rewrite(core.events, 'changingFloor', 'add', (_, floorId) => { + if (!main.replayChecking) { + updateShadow(); + setCanvasFilterByFloorId(floorId); + } + }); + // 初始化画布信息 + Mota.rewrite(core.ui, 'deleteAllCanvas', 'add', () => { + if (main.mode === 'play' && !main.replayChecking) initShadowCanvas(); + }); } const shadowInfo: Partial> = { diff --git a/src/plugin/ui/book.tsx b/src/plugin/ui/book.tsx index e8d4a18..5758206 100644 --- a/src/plugin/ui/book.tsx +++ b/src/plugin/ui/book.tsx @@ -1,4 +1,4 @@ -import { CurrentEnemy } from '../game/enemy/battle'; +import type { CurrentEnemy } from '../game/enemy/battle'; import { has } from '../utils'; export interface ToShowEnemy extends CurrentEnemy { diff --git a/src/plugin/ui/fixed.ts b/src/plugin/ui/fixed.ts index a996291..ef261e9 100644 --- a/src/plugin/ui/fixed.ts +++ b/src/plugin/ui/fixed.ts @@ -1,6 +1,6 @@ import { getDamageColor } from '../utils'; import { ToShowEnemy } from './book'; -import { DamageEnemy } from '../game/enemy/damage'; +import type { DamageEnemy } from '../game/enemy/damage'; import { isMobile } from '../use'; export function getLocFromMouseLoc(x: number, y: number): LocArr { diff --git a/src/plugin/ui/fly.ts b/src/plugin/ui/fly.ts index 5bd5d24..5f126b9 100644 --- a/src/plugin/ui/fly.ts +++ b/src/plugin/ui/fly.ts @@ -1,9 +1,5 @@ import { has } from '../utils'; -export default function init() { - return { splitArea, getMapDrawData }; -} - type BFSFromString = `${FloorIds},${number},${number},${Dir}`; type BFSToString = `${FloorIds},${number},${number}`; diff --git a/src/plugin/ui/statusBar.ts b/src/plugin/ui/statusBar.ts index 6ab47c4..ad53c03 100644 --- a/src/plugin/ui/statusBar.ts +++ b/src/plugin/ui/statusBar.ts @@ -1,9 +1,3 @@ import { ref } from 'vue'; -const status = ref(false); - -export default function init() { - return { statusBarStatus: status }; -} - -export { status }; +export const status = ref(false);