mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-02-28 09:27:07 +08:00
refactor & fix: 插件与进程分离
This commit is contained in:
parent
325a1e85ec
commit
a9c64565e1
@ -23,7 +23,7 @@
|
||||
"jszip": "^3.10.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lz-string": "^1.5.0",
|
||||
"mutate-animate": "^1.3.2",
|
||||
"mutate-animate": "^1.3.3",
|
||||
"three": "^0.149.0",
|
||||
"vue": "^3.3.4"
|
||||
},
|
||||
|
@ -30,8 +30,8 @@ dependencies:
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0
|
||||
mutate-animate:
|
||||
specifier: ^1.3.2
|
||||
version: 1.3.2
|
||||
specifier: ^1.3.3
|
||||
version: 1.3.3
|
||||
three:
|
||||
specifier: ^0.149.0
|
||||
version: 0.149.0
|
||||
@ -2686,19 +2686,6 @@ packages:
|
||||
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
|
||||
dev: true
|
||||
|
||||
/debug@3.2.7:
|
||||
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
||||
requiresBuild: true
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/debug@4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -3557,10 +3544,8 @@ packages:
|
||||
image-size: 0.5.5
|
||||
make-dir: 2.1.0
|
||||
mime: 1.6.0
|
||||
needle: 3.2.0
|
||||
needle: 3.3.1
|
||||
source-map: 0.6.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/lie@3.3.0:
|
||||
@ -3866,8 +3851,8 @@ packages:
|
||||
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
|
||||
dev: true
|
||||
|
||||
/mutate-animate@1.3.2:
|
||||
resolution: {integrity: sha512-d9En7f9EBFHLy4DZtMyAVg6aEyv1+JldM+7I/Fcb2CvGVYxrgl6gqSqYz7W3Ts7SaWW6ckAqJaGVgusvXXv/OA==}
|
||||
/mutate-animate@1.3.3:
|
||||
resolution: {integrity: sha512-iv6ntOfMIWjaPUvKPb51J706qMghenLSukRQhzSrCyjEqUo/SHgWOFc3mK8J6FF/p5T81IinP3U/eCl0RivcdQ==}
|
||||
dev: false
|
||||
|
||||
/nan@2.17.0:
|
||||
@ -3883,17 +3868,14 @@ packages:
|
||||
resolution: {integrity: sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw==}
|
||||
dev: false
|
||||
|
||||
/needle@3.2.0:
|
||||
resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==}
|
||||
/needle@3.3.1:
|
||||
resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==}
|
||||
engines: {node: '>= 4.4.x'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
iconv-lite: 0.6.3
|
||||
sax: 1.2.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
|
@ -1468,11 +1468,11 @@ control.prototype.updateDamage = function (floorId, ctx) {
|
||||
};
|
||||
|
||||
control.prototype._updateDamage_damage = function (floorId, onMap) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts EnemyCollection.render.
|
||||
// Deprecated. See src/game/enemy/damage.ts EnemyCollection.render.
|
||||
};
|
||||
|
||||
control.prototype._updateDamage_extraDamage = function (floorId, onMap) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts EnemyCollection.render.
|
||||
// Deprecated. See src/game/enemy/damage.ts EnemyCollection.render.
|
||||
};
|
||||
|
||||
////// 重绘地图显伤 //////
|
||||
|
@ -319,11 +319,11 @@ core.prototype._loadGameProcess = async function () {
|
||||
if (main.pluginUseCompress) {
|
||||
await main.loadScript(`project/processG.min.js?v=${main.version}`);
|
||||
} else {
|
||||
if (main.mode === 'play') {
|
||||
await main.loadScript(`src/game/index.ts`, true);
|
||||
} else {
|
||||
await main.loadScript(`src/game/index.esm.ts`, true);
|
||||
}
|
||||
// if (main.mode === 'play') {
|
||||
// await main.loadScript(`src/game/index.ts`, true);
|
||||
// } else {
|
||||
// await main.loadScript(`src/game/index.esm.ts`, true);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,43 +103,43 @@ enemys.prototype.getDamageString = function (enemy, x, y, floorId, hero) {
|
||||
|
||||
////// 接下来N个临界值和临界减伤计算 //////
|
||||
enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId, hero) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
// Deprecated. See src/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
};
|
||||
|
||||
/// 未破防临界采用二分计算
|
||||
enemys.prototype._nextCriticals_overAtk = function (enemy) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
// Deprecated. See src/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
};
|
||||
|
||||
enemys.prototype._nextCriticals_special = function (enemy) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
// Deprecated. See src/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
};
|
||||
|
||||
enemys.prototype._nextCriticals_useBinarySearch = function (enemy) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
// Deprecated. See src/game/enemy/damage.ts DamageEnemy.calCritical.
|
||||
};
|
||||
|
||||
////// N防减伤计算 //////
|
||||
enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId, hero) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts DamageEnemy.calDefDamage.
|
||||
// Deprecated. See src/game/enemy/damage.ts DamageEnemy.calDefDamage.
|
||||
};
|
||||
|
||||
enemys.prototype.getEnemyInfo = function (enemy, hero, x, y, floorId) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts
|
||||
// Deprecated. See src/game/enemy/damage.ts
|
||||
};
|
||||
|
||||
////// 获得战斗伤害信息(实际伤害计算函数) //////
|
||||
enemys.prototype.getDamageInfo = function (enemy, hero, x, y, floorId) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts
|
||||
// Deprecated. See src/game/enemy/damage.ts
|
||||
};
|
||||
|
||||
////// 获得在某个勇士属性下怪物伤害 //////
|
||||
enemys.prototype.getDamage = function (enemy, x, y, floorId, hero) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts
|
||||
// Deprecated. See src/game/enemy/damage.ts
|
||||
};
|
||||
|
||||
enemys.prototype._getDamage = function (enemy, hero, x, y, floorId) {
|
||||
// Deprecated. See src/plugin/game/enemy/damage.ts
|
||||
// Deprecated. See src/game/enemy/damage.ts
|
||||
};
|
||||
|
||||
////// 获得当前楼层的怪物列表 //////
|
||||
|
@ -27,9 +27,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue';
|
||||
import { mainUi, fixedUi } from './core/main/init/ui';
|
||||
import { hook } from '@/core/main/game';
|
||||
|
||||
onMounted(() => {
|
||||
const { hook } = Mota.requireAll('var');
|
||||
hook.emit('mounted');
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
// todo: 更改utils.ts的形式,使common文件夹可以同时在渲染进程和游戏进程使用
|
||||
import { has } from '@/plugin/utils';
|
||||
|
||||
function has<T>(value: T): value is NonNullable<T> {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
export interface EmitableEvent {
|
||||
[event: string]: (...params: any) => any;
|
||||
@ -21,6 +24,8 @@ type EmitFn<F extends (...params: any) => any> = (
|
||||
...params: Parameters<F>
|
||||
) => any;
|
||||
|
||||
console.log(1);
|
||||
|
||||
export class EventEmitter<T extends EmitableEvent = {}> {
|
||||
protected events: {
|
||||
[P in keyof T]?: Listener<T[P]>[];
|
||||
|
@ -1,49 +1,33 @@
|
||||
import { BgmController, bgm } from './audio/bgm';
|
||||
import { SoundController, sound } from './audio/sound';
|
||||
import { EventEmitter } from './common/eventEmitter';
|
||||
import { loading, readyAllResource } from './loader/load';
|
||||
import { SoundController, SoundEffect, sound } from './audio/sound';
|
||||
import { readyAllResource } from './loader/load';
|
||||
import {
|
||||
Resource,
|
||||
ResourceStore,
|
||||
ResourceType,
|
||||
ZippedResource,
|
||||
resource,
|
||||
zipResource
|
||||
} from './loader/resource';
|
||||
import { UiController } from './main/custom/ui';
|
||||
import { GameEvent, gameListener, hook } from './main/game';
|
||||
import { Focus, GameUi, UiController } from './main/custom/ui';
|
||||
import { GameStorage } from './main/storage';
|
||||
// import { resolvePlugin } from './plugin';
|
||||
import './main/init/';
|
||||
import './main/custom/toolbar';
|
||||
import { fixedUi, mainUi } from './main/init/ui';
|
||||
import { gameKey } from './main/init/hotkey';
|
||||
import { mainSetting, settingStorage } from './main/setting';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import {
|
||||
MotaSetting,
|
||||
SettingDisplayer,
|
||||
mainSetting,
|
||||
settingStorage
|
||||
} from './main/setting';
|
||||
import { KeyCode } from '@/plugin/keyCodes';
|
||||
import { status } from '@/plugin/ui/statusBar';
|
||||
import './plugin';
|
||||
import './package';
|
||||
|
||||
// interface AncTePlugin {
|
||||
// pop: ReturnType<typeof import('../plugin/pop').default>;
|
||||
// use: ReturnType<typeof import('../plugin/use').default>;
|
||||
// animate: ReturnType<typeof import('../plugin/animateController').default>;
|
||||
// utils: ReturnType<typeof import('../plugin/utils').default>;
|
||||
// status: ReturnType<typeof import('../plugin/ui/statusBar').default>;
|
||||
// fly: ReturnType<typeof import('../plugin/ui/fly').default>;
|
||||
// chase: ReturnType<typeof import('../plugin/chase/chase').default>;
|
||||
// webglUtils: ReturnType<typeof import('../plugin/webgl/utils').default>;
|
||||
// shadow: ReturnType<typeof import('../plugin/shadow/shadow').default>;
|
||||
// gameShadow: ReturnType<
|
||||
// typeof import('../plugin/shadow/gameShadow').default
|
||||
// >;
|
||||
// achievement: ReturnType<typeof import('../plugin/ui/achievement').default>;
|
||||
// completion: ReturnType<typeof import('../plugin/completion').default>;
|
||||
// path: ReturnType<typeof import('../plugin/fx/path').default>;
|
||||
// gameCanvas: ReturnType<typeof import('../plugin/fx/gameCanvas').default>;
|
||||
// noise: ReturnType<typeof import('../plugin/fx/noise').default>;
|
||||
// smooth: ReturnType<typeof import('../plugin/fx/smoothView').default>;
|
||||
// frag: ReturnType<typeof import('../plugin/fx/frag').default>;
|
||||
// }
|
||||
import { AudioPlayer } from './audio/audio';
|
||||
import { CustomToolbar } from './main/custom/toolbar';
|
||||
import { Hotkey } from './main/custom/hotkey';
|
||||
import { Keyboard } from './main/custom/keyboard';
|
||||
|
||||
// export interface Mota {
|
||||
// sound: SoundController;
|
||||
@ -81,19 +65,38 @@ function ready() {
|
||||
readyAllResource();
|
||||
// loading.once('coreInit', resolvePlugin);
|
||||
}
|
||||
ready();
|
||||
|
||||
// ----- 类注册
|
||||
Mota.register('class', 'AudioPlayer', AudioPlayer);
|
||||
Mota.register('class', 'BgmController', BgmController);
|
||||
Mota.register('class', 'CustomToolbar', CustomToolbar);
|
||||
Mota.register('class', 'Focus', Focus);
|
||||
Mota.register('class', 'GameStorage', GameStorage);
|
||||
Mota.register('class', 'GameUi', GameUi);
|
||||
Mota.register('class', 'Hotkey', Hotkey);
|
||||
Mota.register('class', 'Keyboard', Keyboard);
|
||||
Mota.register('class', 'MotaSetting', MotaSetting);
|
||||
Mota.register('class', 'Resource', Resource);
|
||||
Mota.register('class', 'ResourceStore', ResourceStore);
|
||||
Mota.register('class', 'SettingDisplayer', SettingDisplayer);
|
||||
Mota.register('class', 'SoundController', SoundController);
|
||||
Mota.register('class', 'SoundEffect', SoundEffect);
|
||||
Mota.register('class', 'UiController', UiController);
|
||||
Mota.register('class', 'ZippedResource', ZippedResource);
|
||||
// ----- 函数注册
|
||||
|
||||
// ----- 变量注册
|
||||
Mota.register('var', 'mainUi', mainUi);
|
||||
Mota.register('var', 'fixedUi', fixedUi);
|
||||
Mota.register('var', 'hook', hook);
|
||||
Mota.register('var', 'gameListener', gameListener);
|
||||
Mota.register('var', 'bgm', bgm);
|
||||
Mota.register('var', 'sound', sound);
|
||||
Mota.register('var', 'gameKey', gameKey);
|
||||
Mota.register('var', 'loading', loading);
|
||||
Mota.register('var', 'mainSetting', mainSetting);
|
||||
Mota.register('var', 'KeyCode', KeyCode);
|
||||
Mota.register('var', 'resource', resource);
|
||||
Mota.register('var', 'zipResource', zipResource);
|
||||
Mota.register('var', 'settingStorage', settingStorage);
|
||||
Mota.register('var', 'status', status);
|
||||
|
||||
// ----- 模块注册
|
||||
ready();
|
||||
|
@ -7,13 +7,6 @@ import {
|
||||
resource as res
|
||||
} from './resource';
|
||||
|
||||
interface GameLoadEvent extends EmitableEvent {
|
||||
coreLoaded: () => void;
|
||||
autotileLoaded: () => void;
|
||||
coreInit: () => void;
|
||||
materialLoaded: () => void;
|
||||
}
|
||||
|
||||
const info = resource;
|
||||
|
||||
/**
|
||||
@ -35,6 +28,7 @@ export function readyAllResource() {
|
||||
* 开发时的加载
|
||||
*/
|
||||
/* @__PURE__ */ async function readyDevResource() {
|
||||
const loading = Mota.require('var', 'loading');
|
||||
const loadData = (await import('../../data/resource-dev.json')).default;
|
||||
|
||||
loadData.forEach(v => {
|
||||
@ -50,79 +44,3 @@ export function readyAllResource() {
|
||||
animates.active();
|
||||
});
|
||||
}
|
||||
|
||||
class GameLoading extends EventEmitter<GameLoadEvent> {
|
||||
private autotileLoaded: number = 0;
|
||||
private autotileNum?: number;
|
||||
private autotileListened: boolean = false;
|
||||
|
||||
private materialsNum: number = main.materials.length;
|
||||
private materialsLoaded: number = 0;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.on(
|
||||
'coreInit',
|
||||
() => {
|
||||
this.autotileNum = Object.keys(
|
||||
core.material.icons.autotile
|
||||
).length;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
this.on('materialLoaded', () => {
|
||||
core.loader._loadMaterials_afterLoad();
|
||||
});
|
||||
}
|
||||
|
||||
addMaterialLoaded() {
|
||||
this.once('coreInit', () => {
|
||||
this.materialsLoaded++;
|
||||
if (this.materialsLoaded === this.materialsNum) {
|
||||
this.emit('materialLoaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addAutotileLoaded() {
|
||||
this.once('coreInit', () => {
|
||||
this.autotileLoaded++;
|
||||
if (this.autotileLoaded === this.autotileNum) {
|
||||
this.emit('autotileLoaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 当自动原件加载完毕时
|
||||
* @param autotiles 自动原件数组
|
||||
*/
|
||||
onAutotileLoaded(
|
||||
autotiles: Partial<Record<AllIdsOf<'autotile'>, HTMLImageElement>>
|
||||
) {
|
||||
if (this.autotileListened) return;
|
||||
this.autotileListened = true;
|
||||
this.on('autotileLoaded', () => {
|
||||
const keys = Object.keys(
|
||||
core.material.icons.autotile
|
||||
) as AllIdsOf<'autotile'>[];
|
||||
|
||||
keys.forEach(v => {
|
||||
core.material.images.autotile[v] = autotiles[v]!;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
core.maps._makeAutotileEdges();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const loading = new GameLoading();
|
||||
|
||||
declare global {
|
||||
interface Main {
|
||||
loading: GameLoading;
|
||||
}
|
||||
}
|
||||
main.loading = loading;
|
||||
|
@ -4,7 +4,6 @@ import { ensureArray } from '@/plugin/utils';
|
||||
import { has } from '@/plugin/utils';
|
||||
import JSZip from 'jszip';
|
||||
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
|
||||
import { loading } from './load';
|
||||
|
||||
// todo: 应当用register去注册资源类型,然后进行分块处理
|
||||
|
||||
@ -59,6 +58,7 @@ export class Resource<
|
||||
}
|
||||
|
||||
protected onLoad(v: ResourceData[T]) {
|
||||
const loading = Mota.require('var', 'loading');
|
||||
// 资源类型处理
|
||||
if (this.type === 'fonts') {
|
||||
document.fonts.add(new FontFace(this.name, v as ArrayBuffer));
|
||||
|
@ -40,6 +40,8 @@ export interface HotkeyJSON {
|
||||
assist: number;
|
||||
}
|
||||
|
||||
console.log(2);
|
||||
|
||||
export class Hotkey extends EventEmitter<HotkeyEvent> {
|
||||
static list: Hotkey[];
|
||||
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
import { gameKey } from '../init/hotkey';
|
||||
import { unwarpBinary } from './hotkey';
|
||||
import { fixedUi } from '../init/ui';
|
||||
import { hook } from '../game';
|
||||
|
||||
interface CustomToolbarEvent extends EmitableEvent {
|
||||
add: (item: ValueOf<ToolbarItemMap>) => void;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { debounce } from 'lodash-es';
|
||||
import { gameListener, hook } from '../game';
|
||||
import { fixedUi, mainUi } from './ui';
|
||||
import { ref } from 'vue';
|
||||
import { sleep } from 'mutate-animate';
|
||||
@ -38,6 +37,7 @@ const closeFixed = () => {
|
||||
// todo: 应当在这里实现查看临界与特殊属性的功能
|
||||
export let hovered: Block | null;
|
||||
|
||||
const { hook, gameListener } = Mota.requireAll('var');
|
||||
gameListener.on('hoverBlock', block => {
|
||||
closeFixed();
|
||||
hovered = block;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import * as UI from '@ui/.';
|
||||
import * as MiscUI from './misc';
|
||||
import { GameUi, UiController } from '../custom/ui';
|
||||
import { hook } from '../game';
|
||||
|
||||
export const mainUi = new UiController();
|
||||
mainUi.register(
|
||||
@ -36,6 +35,7 @@ fixedUi.register(
|
||||
);
|
||||
fixedUi.showAll();
|
||||
|
||||
const hook = Mota.require('var', 'hook');
|
||||
hook.once('mounted', () => {
|
||||
const ui = document.getElementById('ui-main')!;
|
||||
const fixed = document.getElementById('ui-fixed')!;
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { FunctionalComponent, reactive } from 'vue';
|
||||
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
|
||||
import { loading } from '../loader/load';
|
||||
import { hook } from './game';
|
||||
import { GameStorage } from './storage';
|
||||
import { has, triggerFullscreen } from '@/plugin/utils';
|
||||
import { createSettingComponents } from './init/settings';
|
||||
@ -478,6 +476,7 @@ mainSetting
|
||||
)
|
||||
);
|
||||
|
||||
const loading = Mota.require('var', 'loading');
|
||||
loading.once('coreInit', () => {
|
||||
mainSetting.reset({
|
||||
'screen.fullscreen': !!document.fullscreenElement,
|
||||
@ -497,6 +496,7 @@ loading.once('coreInit', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const { hook } = Mota.requireAll('var');
|
||||
hook.on('reset', () => {
|
||||
mainSetting.reset({
|
||||
'action.autoSkill': flags.autoSkill ?? true
|
||||
|
@ -27,7 +27,6 @@ import * as frag from '@/plugin/fx/frag';
|
||||
import * as use from '@/plugin/use';
|
||||
import * as gameCanvas from '@/plugin/fx/gameCanvas';
|
||||
import * as smooth from '@/plugin/fx/smoothView';
|
||||
import { loading } from './loader/load';
|
||||
|
||||
Mota.Plugin.register('shadow_r', shadow, shadow.init);
|
||||
Mota.Plugin.register('gameShadow_r', gameShadow, gameShadow.init);
|
||||
@ -40,10 +39,6 @@ Mota.Plugin.register('use_r', use);
|
||||
Mota.Plugin.register('gameCanvas_r', gameCanvas);
|
||||
Mota.Plugin.register('smooth_r', smooth, smooth.init);
|
||||
|
||||
loading.once('coreInit', () => {
|
||||
Mota.Plugin.init();
|
||||
});
|
||||
|
||||
// // todo: 将插件更改为注册形式,分为渲染进程和游戏进程两部分,同时分配优先级
|
||||
|
||||
// export function resolvePlugin() {
|
||||
|
239
src/game/enemy/battle.ts
Normal file
239
src/game/enemy/battle.ts
Normal file
@ -0,0 +1,239 @@
|
||||
import { DamageEnemy, ensureFloorDamage, getSingleEnemy } from './damage';
|
||||
import { findDir, has } from '../../plugin/game/utils';
|
||||
|
||||
export interface CurrentEnemy {
|
||||
enemy: DamageEnemy;
|
||||
onMapEnemy: DamageEnemy[];
|
||||
}
|
||||
|
||||
export function getEnemy(
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = core.status.maps[floorId].enemy.list.find(v => {
|
||||
return v.x === x && v.y === y;
|
||||
});
|
||||
if (!enemy) {
|
||||
throw new Error(
|
||||
`Get null when getting enemy on '${x},${y}' in '${floorId}'`
|
||||
);
|
||||
}
|
||||
return enemy;
|
||||
}
|
||||
|
||||
export function canBattle(
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
return damage < core.status.hero.hp;
|
||||
}
|
||||
|
||||
export function battle(
|
||||
x: number,
|
||||
y: number,
|
||||
force: boolean = false,
|
||||
callback?: () => void
|
||||
) {
|
||||
core.saveAndStopAutomaticRoute();
|
||||
const enemy = getEnemy(x, y);
|
||||
// 非强制战斗
|
||||
if (!core.enemys.canBattle(x, y) && !force && !core.status.event.id) {
|
||||
core.stopSound();
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('你打不过此怪物!', enemy.id);
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
}
|
||||
// 自动存档
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
// 战前事件
|
||||
// 战后事件
|
||||
afterBattle(enemy, x, y);
|
||||
callback?.();
|
||||
}
|
||||
|
||||
export function afterBattle(enemy: DamageEnemy, x?: number, y?: number) {
|
||||
const floorId = core.status.floorId;
|
||||
const special = enemy.info.special;
|
||||
|
||||
// 播放战斗动画
|
||||
let animate: AnimationIds = 'hand';
|
||||
// 检查当前装备是否存在攻击动画
|
||||
const equipId = core.getEquip(0);
|
||||
if (equipId && (core.material.items[equipId].equip || {}).animate)
|
||||
animate = core.material.items[equipId].equip.animate;
|
||||
|
||||
// 检查该动画是否存在SE,如果不存在则使用默认音效
|
||||
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
|
||||
|
||||
// 战斗伤害
|
||||
const info = enemy.calDamage(core.status.hero);
|
||||
const damage = info.damage;
|
||||
// 判定是否致死
|
||||
if (damage >= core.status.hero.hp) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar(false, true);
|
||||
core.events.lose('战斗失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 扣减体力值并记录统计数据
|
||||
core.status.hero.hp -= damage;
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
);
|
||||
core.status.hero.mdef -=
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
|
||||
}
|
||||
|
||||
// 极昼永夜
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
|
||||
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
|
||||
// core.plugin.study.declineStudiedSkill();
|
||||
// }
|
||||
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (special.includes(25) && has(x) && has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
// 获得金币
|
||||
const money = enemy.enemy.money;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
|
||||
// 获得经验
|
||||
const exp = enemy.enemy.exp;
|
||||
core.status.hero.exp += exp;
|
||||
core.status.hero.statistics.exp += exp;
|
||||
|
||||
const hint =
|
||||
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
|
||||
core.drawTip(hint, enemy.id);
|
||||
|
||||
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
|
||||
core.setFlag('blade', false);
|
||||
}
|
||||
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
|
||||
core.setFlag('shield', false);
|
||||
}
|
||||
|
||||
// 事件的处理
|
||||
const todo: MotaEvent = [];
|
||||
|
||||
// 战后事件
|
||||
if (has(core.status.floorId)) {
|
||||
const loc = `${x},${y}` as LocString;
|
||||
todo.push(...(core.floors[core.status.floorId].afterBattle[loc] ?? []));
|
||||
}
|
||||
todo.push(...(enemy.enemy.afterBattle ?? []));
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length > 0) core.insertAction(todo, x, y);
|
||||
|
||||
if (has(x) && has(y)) {
|
||||
core.drawAnimate(animate, x, y);
|
||||
core.removeBlock(x, y);
|
||||
} else core.drawHeroAnimate(animate);
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
}
|
||||
|
||||
export function getCurrentEnemys(floorId = core.status.floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
const e = new DamageEnemy(v.enemy);
|
||||
e.calAttribute();
|
||||
e.getRealInfo();
|
||||
e.calDamage();
|
||||
const curr: CurrentEnemy = {
|
||||
enemy: e,
|
||||
onMapEnemy: [v]
|
||||
};
|
||||
enemys.push(curr);
|
||||
used[v.id] = curr.onMapEnemy;
|
||||
} else {
|
||||
used[v.id].push(v);
|
||||
}
|
||||
});
|
||||
|
||||
return enemys.sort((a, b) => {
|
||||
const ad = a.enemy.calDamage().damage;
|
||||
const bd = b.enemy.calDamage().damage;
|
||||
return ad - bd;
|
||||
});
|
||||
}
|
||||
|
||||
export function init() {
|
||||
core.events._sys_battle = function (data: Block, callback?: () => void) {
|
||||
// 检查战前事件
|
||||
const floor = core.floors[core.status.floorId];
|
||||
const beforeBattle: MotaEvent = [];
|
||||
const loc = `${data.x},${data.y}` as LocString;
|
||||
const enemy = getEnemy(data.x, data.y);
|
||||
|
||||
beforeBattle.push(...(floor.beforeBattle[loc] ?? []));
|
||||
beforeBattle.push(...(enemy.enemy.beforeBattle ?? []));
|
||||
|
||||
if (beforeBattle.length > 0) {
|
||||
beforeBattle.push({ type: 'battle', x: data.x, y: data.y });
|
||||
core.clearContinueAutomaticRoute();
|
||||
|
||||
// 自动存档
|
||||
var inAction = core.status.event.id == 'action';
|
||||
if (inAction) {
|
||||
core.insertAction(beforeBattle, data.x, data.y);
|
||||
core.doAction();
|
||||
} else {
|
||||
core.autosave(true);
|
||||
core.insertAction(beforeBattle, data.x, data.y, callback);
|
||||
}
|
||||
} else {
|
||||
this.battle(data.x, data.y, false, callback);
|
||||
}
|
||||
};
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
core.doAction();
|
||||
return;
|
||||
}
|
||||
const [ex, ey] = this.__action_getLoc(
|
||||
data.loc,
|
||||
x,
|
||||
y,
|
||||
prefix
|
||||
) as LocArr;
|
||||
this.battle(ex, ey, true, core.doAction);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,6 +1,12 @@
|
||||
import { getHeroStatusOf, getHeroStatusOn } from '../hero';
|
||||
import { Range, RangeCollection } from '../range';
|
||||
import { checkV2, ensureArray, formatDamage, has, manhattan } from '../utils';
|
||||
import { getHeroStatusOf, getHeroStatusOn } from '@/plugin/game/hero';
|
||||
import { Range, RangeCollection } from '@/plugin/game/range';
|
||||
import {
|
||||
checkV2,
|
||||
ensureArray,
|
||||
formatDamage,
|
||||
has,
|
||||
manhattan
|
||||
} from '@/plugin/game/utils';
|
||||
|
||||
interface HaloType {
|
||||
square: {
|
@ -1,4 +1,4 @@
|
||||
import { getHeroStatusOn } from '../hero';
|
||||
import { getHeroStatusOn } from '@/plugin/game/hero';
|
||||
|
||||
export interface SpecialDeclaration {
|
||||
code: number;
|
@ -1,5 +1,81 @@
|
||||
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
|
||||
import { loading } from '../loader/load';
|
||||
import { EmitableEvent, EventEmitter } from '../core/common/eventEmitter';
|
||||
|
||||
// ----- 加载事件
|
||||
interface GameLoadEvent extends EmitableEvent {
|
||||
coreLoaded: () => void;
|
||||
autotileLoaded: () => void;
|
||||
coreInit: () => void;
|
||||
materialLoaded: () => void;
|
||||
}
|
||||
|
||||
class GameLoading extends EventEmitter<GameLoadEvent> {
|
||||
private autotileLoaded: number = 0;
|
||||
private autotileNum?: number;
|
||||
private autotileListened: boolean = false;
|
||||
|
||||
private materialsNum: number = main.materials.length;
|
||||
private materialsLoaded: number = 0;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.on(
|
||||
'coreInit',
|
||||
() => {
|
||||
this.autotileNum = Object.keys(
|
||||
core.material.icons.autotile
|
||||
).length;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
this.on('materialLoaded', () => {
|
||||
core.loader._loadMaterials_afterLoad();
|
||||
});
|
||||
}
|
||||
|
||||
addMaterialLoaded() {
|
||||
this.once('coreInit', () => {
|
||||
this.materialsLoaded++;
|
||||
if (this.materialsLoaded === this.materialsNum) {
|
||||
this.emit('materialLoaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addAutotileLoaded() {
|
||||
this.once('coreInit', () => {
|
||||
this.autotileLoaded++;
|
||||
if (this.autotileLoaded === this.autotileNum) {
|
||||
this.emit('autotileLoaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 当自动原件加载完毕时
|
||||
* @param autotiles 自动原件数组
|
||||
*/
|
||||
onAutotileLoaded(
|
||||
autotiles: Partial<Record<AllIdsOf<'autotile'>, HTMLImageElement>>
|
||||
) {
|
||||
if (this.autotileListened) return;
|
||||
this.autotileListened = true;
|
||||
this.on('autotileLoaded', () => {
|
||||
const keys = Object.keys(
|
||||
core.material.icons.autotile
|
||||
) as AllIdsOf<'autotile'>[];
|
||||
|
||||
keys.forEach(v => {
|
||||
core.material.images.autotile[v] = autotiles[v]!;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
core.maps._makeAutotileEdges();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const loading = new GameLoading();
|
||||
|
||||
export interface GameEvent extends EmitableEvent {
|
||||
/** Emitted in events.prototype.resetGame. */
|
||||
@ -118,3 +194,9 @@ class GameListener extends EventEmitter<ListenerEvent> {
|
||||
}
|
||||
|
||||
export const gameListener = new GameListener();
|
||||
|
||||
declare global {
|
||||
interface Main {
|
||||
loading: GameLoading;
|
||||
}
|
||||
}
|
@ -1,2 +1,32 @@
|
||||
import './system';
|
||||
import '../plugin/game/index';
|
||||
import { DamageEnemy, EnemyCollection } from './enemy/damage';
|
||||
import {
|
||||
EmitableEvent,
|
||||
EventEmitter,
|
||||
IndexedEventEmitter
|
||||
} from '@/core/common/eventEmitter';
|
||||
import { Range } from '@/plugin/game/range';
|
||||
import { specials } from './enemy/special';
|
||||
import { gameListener, hook, loading } from './game';
|
||||
|
||||
// ----- 类注册
|
||||
Mota.register('class', 'DamageEnemy', DamageEnemy);
|
||||
Mota.register('class', 'EnemyCollection', EnemyCollection);
|
||||
Mota.register('class', 'EventEmitter', EventEmitter);
|
||||
Mota.register('class', 'IndexedEventEmitter', IndexedEventEmitter);
|
||||
Mota.register('class', 'Range', Range);
|
||||
// ----- 函数注册
|
||||
|
||||
// ----- 变量注册
|
||||
Mota.register('var', 'enemySpecials', specials);
|
||||
Mota.register('var', 'hook', hook);
|
||||
Mota.register('var', 'gameListener', gameListener);
|
||||
Mota.register('var', 'loading', loading);
|
||||
// ----- 模块注册
|
||||
|
||||
main.loading = loading;
|
||||
|
||||
loading.once('coreInit', () => {
|
||||
Mota.Plugin.init();
|
||||
});
|
||||
|
@ -6,7 +6,7 @@ import type {
|
||||
EventEmitter,
|
||||
IndexedEventEmitter
|
||||
} from '@/core/common/eventEmitter';
|
||||
import type { loading } from '@/core/loader/load';
|
||||
import type { loading } from './game';
|
||||
import type {
|
||||
Resource,
|
||||
ResourceStore,
|
||||
@ -17,15 +17,15 @@ import type { Hotkey } from '@/core/main/custom/hotkey';
|
||||
import type { Keyboard } from '@/core/main/custom/keyboard';
|
||||
import type { CustomToolbar } from '@/core/main/custom/toolbar';
|
||||
import type { Focus, GameUi, UiController } from '@/core/main/custom/ui';
|
||||
import type { gameListener, hook } from '@/core/main/game';
|
||||
import type { gameListener, hook } from './game';
|
||||
import type {
|
||||
MotaSetting,
|
||||
SettingDisplayer,
|
||||
SettingStorage
|
||||
} from '@/core/main/setting';
|
||||
import type { GameStorage } from '@/core/main/storage';
|
||||
import type { DamageEnemy, EnemyCollection } from '@/plugin/game/enemy/damage';
|
||||
import type { specials } from '@/plugin/game/enemy/special';
|
||||
import type { DamageEnemy, EnemyCollection } from './enemy/damage';
|
||||
import type { specials } from './enemy/special';
|
||||
import type { Range } from '@/plugin/game/range';
|
||||
import type { KeyCode } from '@/plugin/keyCodes';
|
||||
import type { Ref } from 'vue';
|
||||
@ -89,10 +89,13 @@ interface VariableInterface {
|
||||
enemySpecials: typeof specials;
|
||||
}
|
||||
|
||||
interface ModuleInterface {}
|
||||
|
||||
interface SystemInterfaceMap {
|
||||
class: ClassInterface;
|
||||
fn: FunctionInterface;
|
||||
var: VariableInterface;
|
||||
module: ModuleInterface;
|
||||
}
|
||||
|
||||
type InterfaceType = keyof SystemInterfaceMap;
|
||||
@ -374,6 +377,7 @@ class Mota {
|
||||
private static classes: Record<string, any> = {};
|
||||
private static functions: Record<string, any> = {};
|
||||
private static variables: Record<string, any> = {};
|
||||
private static modules: Record<string, any> = {};
|
||||
|
||||
static rewrite = rewrite;
|
||||
static r = r;
|
||||
@ -414,7 +418,9 @@ class Mota {
|
||||
? this.classes
|
||||
: type === 'fn'
|
||||
? this.functions
|
||||
: this.variables;
|
||||
: type === 'var'
|
||||
? this.variables
|
||||
: this.modules;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { createApp } from 'vue';
|
||||
import './game/index';
|
||||
import './core/index';
|
||||
import App from './App.vue';
|
||||
import './styles.less';
|
||||
import 'ant-design-vue/dist/antd.dark.css';
|
||||
import './game/index';
|
||||
import './core/index';
|
||||
|
||||
createApp(App).mount('#root');
|
||||
|
||||
|
@ -5,7 +5,6 @@ import {
|
||||
} from './ui/achievement';
|
||||
import { changeLocalStorage } from './utils';
|
||||
import list from '../data/achievement.json';
|
||||
import { loading } from '@/core/loader/load';
|
||||
|
||||
export const floors: Record<number, FloorIds[]> = {
|
||||
1: ['MT0', 'tower7']
|
||||
@ -22,6 +21,8 @@ export const achiDict: Record<number, number> = {
|
||||
1: 0
|
||||
};
|
||||
|
||||
const loading = Mota.require('var', 'loading');
|
||||
|
||||
loading.once('coreInit', () => {
|
||||
Object.values(floors).forEach((v, i) => {
|
||||
const from = core.floorIds.indexOf(v[0]);
|
||||
|
@ -52,15 +52,15 @@ export function init() {
|
||||
const hso = hyper('sin', 'out');
|
||||
let time2 = Date.now();
|
||||
Mota.rewrite(core.control, '_moveAction_moving', 'front', () => {
|
||||
const t = setting.getValue('screen.smoothView', false) ? 200 : 1;
|
||||
const t = setting.getValue('screen.smoothView', false) ? 200 : 0;
|
||||
if (Date.now() - time2 > 20) tran.mode(hso).time(t).absolute();
|
||||
});
|
||||
Mota.rewrite(core.control, 'moveDirectly', 'front', () => {
|
||||
const t = setting.getValue('screen.smoothView', false) ? 600 : 1;
|
||||
const t = setting.getValue('screen.smoothView', false) ? 600 : 0;
|
||||
time2 = Date.now();
|
||||
tran.mode(hso).time(t).absolute();
|
||||
});
|
||||
Mota.rewrite(core.events, '_changeFloor_beforeChange', 'front', () => {
|
||||
tran.time(1).absolute();
|
||||
tran.time(0).absolute();
|
||||
});
|
||||
}
|
||||
|
@ -1,245 +0,0 @@
|
||||
import { DamageEnemy, ensureFloorDamage, getSingleEnemy } from './damage';
|
||||
import { findDir, has } from '../utils';
|
||||
|
||||
export interface CurrentEnemy {
|
||||
enemy: DamageEnemy;
|
||||
onMapEnemy: DamageEnemy[];
|
||||
}
|
||||
|
||||
export function getEnemy(
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = core.status.maps[floorId].enemy.list.find(v => {
|
||||
return v.x === x && v.y === y;
|
||||
});
|
||||
if (!enemy) {
|
||||
throw new Error(
|
||||
`Get null when getting enemy on '${x},${y}' in '${floorId}'`
|
||||
);
|
||||
}
|
||||
return enemy;
|
||||
}
|
||||
|
||||
export function init() {
|
||||
core.enemys.canBattle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
return damage < core.status.hero.hp;
|
||||
};
|
||||
|
||||
core.events.battle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
force: boolean = false,
|
||||
callback?: () => void
|
||||
) {
|
||||
core.saveAndStopAutomaticRoute();
|
||||
const enemy = getEnemy(x, y);
|
||||
// 非强制战斗
|
||||
if (!core.enemys.canBattle(x, y) && !force && !core.status.event.id) {
|
||||
core.stopSound();
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('你打不过此怪物!', enemy.id);
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
}
|
||||
// 自动存档
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
// 战前事件
|
||||
// 战后事件
|
||||
this.afterBattle(enemy, x, y);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
core.events.afterBattle = function (
|
||||
enemy: DamageEnemy,
|
||||
x?: number,
|
||||
y?: number
|
||||
) {
|
||||
const floorId = core.status.floorId;
|
||||
const special = enemy.info.special;
|
||||
|
||||
// 播放战斗动画
|
||||
let animate: AnimationIds = 'hand';
|
||||
// 检查当前装备是否存在攻击动画
|
||||
const equipId = core.getEquip(0);
|
||||
if (equipId && (core.material.items[equipId].equip || {}).animate)
|
||||
animate = core.material.items[equipId].equip.animate;
|
||||
|
||||
// 检查该动画是否存在SE,如果不存在则使用默认音效
|
||||
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
|
||||
|
||||
// 战斗伤害
|
||||
const info = enemy.calDamage(core.status.hero);
|
||||
const damage = info.damage;
|
||||
// 判定是否致死
|
||||
if (damage >= core.status.hero.hp) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar(false, true);
|
||||
core.events.lose('战斗失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 扣减体力值并记录统计数据
|
||||
core.status.hero.hp -= damage;
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
);
|
||||
core.status.hero.mdef -=
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
|
||||
}
|
||||
|
||||
// 极昼永夜
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
|
||||
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
|
||||
// core.plugin.study.declineStudiedSkill();
|
||||
// }
|
||||
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (special.includes(25) && has(x) && has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
// 获得金币
|
||||
const money = enemy.enemy.money;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
|
||||
// 获得经验
|
||||
const exp = enemy.enemy.exp;
|
||||
core.status.hero.exp += exp;
|
||||
core.status.hero.statistics.exp += exp;
|
||||
|
||||
const hint =
|
||||
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
|
||||
core.drawTip(hint, enemy.id);
|
||||
|
||||
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
|
||||
core.setFlag('blade', false);
|
||||
}
|
||||
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
|
||||
core.setFlag('shield', false);
|
||||
}
|
||||
|
||||
// 事件的处理
|
||||
const todo: MotaEvent = [];
|
||||
|
||||
// 战后事件
|
||||
if (has(core.status.floorId)) {
|
||||
const loc = `${x},${y}` as LocString;
|
||||
todo.push(
|
||||
...(core.floors[core.status.floorId].afterBattle[loc] ?? [])
|
||||
);
|
||||
}
|
||||
todo.push(...(enemy.enemy.afterBattle ?? []));
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length > 0) core.insertAction(todo, x, y);
|
||||
|
||||
if (has(x) && has(y)) {
|
||||
core.drawAnimate(animate, x, y);
|
||||
core.removeBlock(x, y);
|
||||
} else core.drawHeroAnimate(animate);
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
};
|
||||
|
||||
core.events._sys_battle = function (data: Block, callback?: () => void) {
|
||||
// 检查战前事件
|
||||
const floor = core.floors[core.status.floorId];
|
||||
const beforeBattle: MotaEvent = [];
|
||||
const loc = `${data.x},${data.y}` as LocString;
|
||||
const enemy = getEnemy(data.x, data.y);
|
||||
|
||||
beforeBattle.push(...(floor.beforeBattle[loc] ?? []));
|
||||
beforeBattle.push(...(enemy.enemy.beforeBattle ?? []));
|
||||
|
||||
if (beforeBattle.length > 0) {
|
||||
beforeBattle.push({ type: 'battle', x: data.x, y: data.y });
|
||||
core.clearContinueAutomaticRoute();
|
||||
|
||||
// 自动存档
|
||||
var inAction = core.status.event.id == 'action';
|
||||
if (inAction) {
|
||||
core.insertAction(beforeBattle, data.x, data.y);
|
||||
core.doAction();
|
||||
} else {
|
||||
core.autosave(true);
|
||||
core.insertAction(beforeBattle, data.x, data.y, callback);
|
||||
}
|
||||
} else {
|
||||
this.battle(data.x, data.y, false, callback);
|
||||
}
|
||||
};
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
core.doAction();
|
||||
return;
|
||||
}
|
||||
const [ex, ey] = this.__action_getLoc(
|
||||
data.loc,
|
||||
x,
|
||||
y,
|
||||
prefix
|
||||
) as LocArr;
|
||||
this.battle(ex, ey, true, core.doAction);
|
||||
}
|
||||
};
|
||||
|
||||
core.enemys.getCurrentEnemys = function (floorId = core.status.floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
const e = new DamageEnemy(v.enemy);
|
||||
e.calAttribute();
|
||||
e.getRealInfo();
|
||||
e.calDamage();
|
||||
const curr: CurrentEnemy = {
|
||||
enemy: e,
|
||||
onMapEnemy: [v]
|
||||
};
|
||||
enemys.push(curr);
|
||||
used[v.id] = curr.onMapEnemy;
|
||||
} else {
|
||||
used[v.id].push(v);
|
||||
}
|
||||
});
|
||||
|
||||
return enemys.sort((a, b) => {
|
||||
const ad = a.enemy.calDamage().damage;
|
||||
const bd = b.enemy.calDamage().damage;
|
||||
return ad - bd;
|
||||
});
|
||||
};
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { ensureFloorDamage } from '../enemy/damage';
|
||||
import { ensureFloorDamage } from '@/game/enemy/damage';
|
||||
|
||||
export function init() {
|
||||
core.control.updateDamage = function (floorId = core.status.floorId, ctx) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { getEnemy } from '../enemy/battle';
|
||||
import { getEnemy } from '@/game/enemy/battle';
|
||||
import { formatDamage } from '../utils';
|
||||
|
||||
export function init() {
|
||||
|
@ -2,14 +2,12 @@
|
||||
import * as fiveLayer from './fiveLayer';
|
||||
import * as heroFourFrames from './fx/heroFourFrames';
|
||||
import * as itemDetail from './fx/itemDetail';
|
||||
import * as checkBlock from './enemy/checkblock';
|
||||
import * as replay from './replay';
|
||||
import * as ui from './ui';
|
||||
import * as rewrite from './fx/rewrite';
|
||||
import * as halo from './fx/halo';
|
||||
import * as hero from './hero';
|
||||
import * as loopMap from './loopMap';
|
||||
import * as remainEnemy from './enemy/remainEnemy';
|
||||
import * as removeMap from './removeMap';
|
||||
import * as shop from './shop';
|
||||
import * as skill from './skill';
|
||||
@ -18,9 +16,8 @@ import * as study from './study';
|
||||
import * as towerBoss from './towerBoss';
|
||||
import * as utils from './utils';
|
||||
import * as chase from './chase';
|
||||
import * as damage from './enemy/damage';
|
||||
import * as battle from './enemy/battle';
|
||||
import * as special from './enemy/special';
|
||||
import * as remainEnemy from './enemy/remainEnemy';
|
||||
import * as checkBlock from './enemy/checkblock';
|
||||
|
||||
Mota.Plugin.register('utils_g', utils);
|
||||
Mota.Plugin.register('loopMap_g', loopMap, loopMap.init);
|
||||
@ -28,7 +25,6 @@ Mota.Plugin.register('shop_g', shop);
|
||||
Mota.Plugin.register('replay_g', replay, replay.init);
|
||||
Mota.Plugin.register('skillTree_g', skillTree);
|
||||
Mota.Plugin.register('removeMap_g', removeMap);
|
||||
Mota.Plugin.register('remainEnemy_g', remainEnemy);
|
||||
Mota.Plugin.register('chase_g', chase);
|
||||
Mota.Plugin.register('skill_g', skill);
|
||||
Mota.Plugin.register('towerBoss_g', towerBoss);
|
||||
@ -36,13 +32,11 @@ Mota.Plugin.register('fiveLayer_g', fiveLayer, fiveLayer.init);
|
||||
Mota.Plugin.register('heroFourFrames_g', heroFourFrames, heroFourFrames.init);
|
||||
Mota.Plugin.register('rewrite_g', rewrite, rewrite.init);
|
||||
Mota.Plugin.register('itemDetail_g', itemDetail, itemDetail.init);
|
||||
Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
|
||||
Mota.Plugin.register('halo_g', halo);
|
||||
Mota.Plugin.register('study_g', study);
|
||||
Mota.Plugin.register('remainEnemy_g', remainEnemy);
|
||||
Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
|
||||
// todo: 这几个不应该放到插件
|
||||
Mota.Plugin.register('damage_g', damage);
|
||||
Mota.Plugin.register('battle_g', battle, battle.init);
|
||||
Mota.Plugin.register('special_g', special);
|
||||
Mota.Plugin.register('hero_g', hero);
|
||||
Mota.Plugin.register('ui_g', ui, ui.init);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
import { slide } from './utils';
|
||||
|
||||
const list = ['tower6'];
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
export function removeMaps(
|
||||
fromId: FloorIds,
|
||||
toId: FloorIds,
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
import { upgradeSkill } from './skillTree';
|
||||
|
||||
const replayableSettings = ['autoSkill'];
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
let levels: number[] = [];
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import { clip } from './replay.js';
|
||||
import { clip } from './replay';
|
||||
|
||||
// 1000多行,改不动了,原来什么样就什么样吧
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { fixedUi } from '@/core/main/init/ui';
|
||||
import type { DamageEnemy } from './game/enemy/damage';
|
||||
import type { DamageEnemy } from '../game/enemy/damage';
|
||||
import { tip } from './utils';
|
||||
import { ref, Ref } from 'vue';
|
||||
import { hook } from '@/core/main/game';
|
||||
|
||||
export interface MarkInfo<T extends EnemyIds> {
|
||||
id: T;
|
||||
@ -35,7 +34,7 @@ const marked: MarkInfo<EnemyIds>[] = [];
|
||||
*/
|
||||
export function markEnemy(id: EnemyIds) {
|
||||
if (hasMarkedEnemy(id)) return;
|
||||
const { DamageEnemy } = Mota.Plugin.require('damage_g');
|
||||
const DamageEnemy = Mota.require('class', 'DamageEnemy');
|
||||
const enemy = new DamageEnemy(core.material.enemys[id]);
|
||||
enemy.calAttribute();
|
||||
enemy.getRealInfo();
|
||||
@ -159,6 +158,7 @@ export function hasMarkedEnemy(id: EnemyIds) {
|
||||
return marked.some(v => v.id === id);
|
||||
}
|
||||
|
||||
const hook = Mota.require('var', 'hook');
|
||||
hook.on('statusBarUpdate', () => {
|
||||
checkMarkedEnemy();
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { CurrentEnemy } from '../game/enemy/battle';
|
||||
import type { CurrentEnemy } from '../../game/enemy/battle';
|
||||
import { has } from '../utils';
|
||||
|
||||
export interface ToShowEnemy extends CurrentEnemy {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { getDamageColor } from '../utils';
|
||||
import { ToShowEnemy } from './book';
|
||||
import type { DamageEnemy } from '../game/enemy/damage';
|
||||
import type { DamageEnemy } from '../../game/enemy/damage';
|
||||
import { isMobile } from '../use';
|
||||
|
||||
export function getLocFromMouseLoc(x: number, y: number): LocArr {
|
||||
|
2
src/types/enemy.d.ts
vendored
2
src/types/enemy.d.ts
vendored
@ -272,8 +272,6 @@ interface Enemys {
|
||||
floorId?: FloorIds,
|
||||
dir?: Dir | 'none' | (Dir | 'none')[]
|
||||
): boolean;
|
||||
|
||||
getCurrentEnemys(floorId: FloorIds): any[];
|
||||
}
|
||||
|
||||
declare const enemys: new () => Enemys;
|
||||
|
3
src/types/event.d.ts
vendored
3
src/types/event.d.ts
vendored
@ -758,9 +758,6 @@ interface Events extends EventData {
|
||||
*/
|
||||
tryUseItem(itemId: ItemIdOf<'tools' | 'constants'>): void;
|
||||
|
||||
beforeBattle(): boolean;
|
||||
afterBattle(enemy: DamageEnemy, x?: number, y?: number): void;
|
||||
|
||||
_sys_battle(data: Block, callback?: () => void): void;
|
||||
|
||||
_action_battle(data: any, x?: number, y?: number, prefix?: any): void;
|
||||
|
@ -32,7 +32,7 @@
|
||||
import { onMounted, onUpdated, ref, watch } from 'vue';
|
||||
import Box from '../components/box.vue';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import type { DamageEnemy } from '@/plugin/game/enemy/damage';
|
||||
import type { DamageEnemy } from '@/game/enemy/damage';
|
||||
import { nextFrame } from '@/plugin/utils';
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -68,7 +68,6 @@ import { Matrix4 } from '../plugin/webgl/matrix';
|
||||
import { doByInterval, keycode } from '../plugin/utils';
|
||||
import { KeyCode } from '../plugin/keyCodes';
|
||||
import { triggerFullscreen } from '../plugin/utils';
|
||||
import { loading } from '../core/loader/load';
|
||||
import { isMobile } from '../plugin/use';
|
||||
import { GameUi } from '@/core/main/custom/ui';
|
||||
import { gameKey } from '@/core/main/init/hotkey';
|
||||
@ -308,6 +307,8 @@ onMounted(async () => {
|
||||
start = document.getElementById('start') as HTMLDivElement;
|
||||
background = document.getElementById('background') as HTMLImageElement;
|
||||
|
||||
const loading = Mota.require('var', 'loading');
|
||||
|
||||
loading.once('coreInit', async () => {
|
||||
window.addEventListener('resize', resize);
|
||||
resize();
|
||||
|
Loading…
Reference in New Issue
Block a user