@@ -10,34 +10,57 @@
diff --git a/src/initPlugin.ts b/src/initPlugin.ts
index b570cd1..95348eb 100644
--- a/src/initPlugin.ts
+++ b/src/initPlugin.ts
@@ -1,10 +1,13 @@
// 需要引入所有的插件
import pop from './plugin/pop';
import ui from './plugin/uiController';
+import use from './plugin/use';
+import animate from './plugin/animateController';
+import utils from './plugin/utils';
window.addEventListener('load', () => {
// 每个引入的插件都要在这里执行,否则不会被转发
- const toForward: any[] = [pop(), ui()];
+ const toForward: any[] = [pop(), ui(), use(), animate(), utils()];
// 初始化所有插件,并转发到core上
(async function () {
diff --git a/src/main.ts b/src/main.ts
index 3b6df23..7470915 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,5 +1,6 @@
import { createApp } from 'vue';
import App from './App.vue';
import './styles.less';
+import 'ant-design-vue/dist/antd.dark.css';
createApp(App).mount('#root');
diff --git a/src/plugin/animateController.ts b/src/plugin/animateController.ts
new file mode 100644
index 0000000..3a13a16
--- /dev/null
+++ b/src/plugin/animateController.ts
@@ -0,0 +1,32 @@
+const animation: ((time: number) => void)[] = [];
+
+let animateTime = 0;
+
+export default function init() {
+ core.registerAnimationFrame('animate', true, time => {
+ if (time - animateTime <= core.values.animateSpeed) return;
+ for (const fn of animation) {
+ fn(time);
+ }
+ animateTime = core.animateFrame.animateTime;
+ });
+ return { addAnimate, removeAnimate };
+}
+
+/**
+ * 添加一个动画
+ * @param fn 要添加的函数
+ */
+export function addAnimate(fn: (time: number) => void) {
+ animation.push(fn);
+}
+
+/**
+ * 移除一个动画
+ * @param fn 要移除的函数
+ */
+export function removeAnimate(fn: (time: number) => void) {
+ const index = animation.findIndex(v => v === fn);
+ if (index === -1)
+ throw new ReferenceError('No such function in animation.');
+}
diff --git a/src/plugin/use.ts b/src/plugin/use.ts
index c071fc1..9f4946b 100644
--- a/src/plugin/use.ts
+++ b/src/plugin/use.ts
@@ -1,5 +1,5 @@
export default function init() {
- return { useDrag, useWheel };
+ return { useDrag, useWheel, isMobile };
}
/**
@@ -55,3 +55,8 @@ export function useWheel(
fn(e.deltaX, e.deltaY, e.deltaZ, e);
});
}
+
+/**
+ * 是否是移动设备
+ */
+export const isMobile = matchMedia('(max-width: 600px)').matches;
diff --git a/src/plugin/utils.ts b/src/plugin/utils.ts
new file mode 100644
index 0000000..d278e13
--- /dev/null
+++ b/src/plugin/utils.ts
@@ -0,0 +1,27 @@
+import { isNil } from 'lodash';
+
+export default function init() {
+ return { has, getDamageColor };
+}
+
+/**
+ * 判定一个值是否不是undefined或null
+ * @param value 要判断的值
+ */
+export function has
(value: T): value is NonNullable {
+ return !isNil(value);
+}
+
+/**
+ * 根据伤害大小获取颜色
+ * @param damage 伤害大小
+ */
+export function getDamageColor(damage: number): string {
+ if (typeof damage !== 'number') return '#f00';
+ if (damage === 0) return '#2f2';
+ if (damage < 0) return '#7f7';
+ if (damage < core.status.hero.hp / 3) return '#fff';
+ if (damage < (core.status.hero.hp * 2) / 3) return '#ff4';
+ if (damage < core.status.hero.hp) return '#f22';
+ return '#f00';
+}
diff --git a/src/types/core.d.ts b/src/types/core.d.ts
index 0339b17..440033c 100644
--- a/src/types/core.d.ts
+++ b/src/types/core.d.ts
@@ -161,6 +161,10 @@ type Core = {
readonly icons: { [x: string]: HTMLImageElement };
};
+ readonly values: {
+ animateSpeed: number;
+ };
+
readonly materials: string[];
readonly control: control;
@@ -317,3 +321,7 @@ declare const main: main;
declare const core: Core;
declare const flags: { [x: string]: any };
declare const hero: HeroStatus;
+
+interface Window {
+ readonly core: Core;
+}
diff --git a/src/types/enemy.d.ts b/src/types/enemy.d.ts
index c58016c..36b46dd 100644
--- a/src/types/enemy.d.ts
+++ b/src/types/enemy.d.ts
@@ -131,7 +131,7 @@ declare class enemys {
* @param floorId 地图id,可选
* @returns 敌人集合,按伤害升序排列,支持多朝向怪合并
*/
- getCurrentEnemys(floorId?: string): Enemy[];
+ getCurrentEnemys(floorId?: string): (Enemy & DetailedEnemy)[];
/**
* 检查某些楼层是否还有漏打的(某种)敌人
diff --git a/src/types/icon.d.ts b/src/types/icon.d.ts
index 7176a09..22376c7 100644
--- a/src/types/icon.d.ts
+++ b/src/types/icon.d.ts
@@ -4,11 +4,17 @@ declare class icons {
getIcons(): void;
/** 根据ID获得其类型 */
- getClsFromId(id?: string): string;
+ getClsFromId(id?: string): BlockCls;
/** 获得所有图标的ID */
getAllIconIds(): void;
/** 根据图块数字或ID获得所在的tileset和坐标信息 */
getTilesetOffset(id?: string): void;
+
+ /**
+ * 获取图块的帧数
+ * @param cls 图块类型
+ */
+ getAnimateFrames(cls: BlockCls): 1 | 2 | 4;
}
diff --git a/src/types/plugin.d.ts b/src/types/plugin.d.ts
index 760f4fb..73a683e 100644
--- a/src/types/plugin.d.ts
+++ b/src/types/plugin.d.ts
@@ -4,7 +4,7 @@ type Ref = {
value: T;
};
-interface PluginDeclaration {
+interface PluginDeclaration extends PluginUtils {
/**
* 添加函数 例:添加弹出文字,像这个就可以使用core.addPop或core.plugin.addPop调用
* @param px 弹出的横坐标
@@ -25,6 +25,9 @@ interface PluginDeclaration {
/** ui栈 */
readonly uiStack: Ref;
+ /** 是否是移动设备 */
+ readonly isMobile: boolean;
+
/**
* 向一个元素添加拖拽事件
* @param ele 目标元素
@@ -48,6 +51,32 @@ interface PluginDeclaration {
ele: HTMLElement,
fn: (x: number, y: number, z: number, e: WheelEvent) => void
): void;
+
+ /**
+ * 添加一个动画
+ * @param fn 要添加的函数
+ */
+ addAnimate(fn: (time: number) => void);
+
+ /**
+ * 移除一个动画
+ * @param fn 要移除的函数
+ */
+ removeAnimate(fn: (time: number) => void);
+}
+
+interface PluginUtils {
+ /**
+ * 判定一个值是否不是undefined或null
+ * @param value 要判断的值
+ */
+ has(value: T): value is NonNullable;
+
+ /**
+ * 根据伤害大小获取颜色
+ * @param damage 伤害大小
+ */
+ getDamageColor(damage: number): string;
}
type Forward = {
diff --git a/src/types/util.d.ts b/src/types/util.d.ts
index 59f5422..d12eb72 100644
--- a/src/types/util.d.ts
+++ b/src/types/util.d.ts
@@ -100,7 +100,7 @@ declare class utils {
* @param onMap 可选,true表示用于地图显伤,结果总字符数最多为5,否则最多为6
* @returns 格式化结果
*/
- formatBigNumber(x: number, onMap?: boolean): string;
+ formatBigNumber(x: number, onMap?: boolean, onCritical?: boolean): string;
/** 变速移动 */
applyEasing(mode?: string): (number) => number;
@@ -402,6 +402,16 @@ type direction = 'up' | 'down' | 'left' | 'right';
type move = 'forward' | direction;
type loc = { direction: direction; x: number; y: number };
type rgbarray = [number, number, number, number];
+type BlockCls =
+ | 'terrain'
+ | 'animate'
+ | 'enemy'
+ | 'item'
+ | 'enemy48'
+ | 'npcs'
+ | 'npc48'
+ | 'autotile'
+ | 'tilesets';
type Events = MotaAction[] | string;
@@ -515,7 +525,7 @@ type Enemy = {
id: string;
name: string;
displayIdInBook: string;
- special: number | number[];
+ special: number[];
hp: number;
atk: number;
def: number;
@@ -525,6 +535,19 @@ type Enemy = {
[key: string]: any;
};
+type DetailedEnemy = {
+ name: string;
+ specialText: string[];
+ specialColor: (string | rgbarray)[];
+ damage: number;
+ critical: number;
+ criticalDamage: number;
+ defDamage: number;
+ toShowSpecial?: string[];
+ toShowColor?: any[];
+ damageColor?: string;
+};
+
type Item = {
cls: string;
[key: string]: any;
diff --git a/src/ui/book.vue b/src/ui/book.vue
index 51bc1f6..8e822c4 100644
--- a/src/ui/book.vue
+++ b/src/ui/book.vue
@@ -1,20 +1,87 @@
-
-
- test{{ i }}
-
+
diff --git a/vite.config.ts b/vite.config.ts
index c5f68f0..24ed2c2 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -2,6 +2,7 @@ import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import legacy from '@vitejs/plugin-legacy';
import components from 'unplugin-vue-components/vite';
+import vuejsx from '@vitejs/plugin-vue-jsx'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
import motaConfig from './mota.config';
@@ -11,6 +12,7 @@ const FSHOST = 'http://127.0.0.1:3000/';
export default defineConfig({
plugins: [
vue(),
+ vuejsx(),
legacy({
targets: ['defaults', 'not IE 11'],
polyfills: true,