diff --git a/packages-user/client-modules/src/ui/book.tsx b/packages-user/client-modules/src/ui/book.tsx index c3dc2fb..35ca6ae 100644 --- a/packages-user/client-modules/src/ui/book.tsx +++ b/packages-user/client-modules/src/ui/book.tsx @@ -12,6 +12,7 @@ import { IUIPropsBase } from './types'; export interface BookProps extends IUIPropsBase {} +/** 怪物手册组件的 props 声明 */ const bookProps = { props: ['controller', 'instance', 'state'] } satisfies SetupComponentOptions; @@ -34,7 +35,9 @@ const nameFont = Font.defaults({ size: 15, weight: 700 }); /** 特殊名与属性字体 */ const statFont = Font.defaults({ size: 12 }); +/** 怪物手册列表组件 */ export const Book = defineComponent(props => { + /** 当前地图的怪物上下文 */ const ctx = props.state.enemyContext; // 按怪物图块数字去重,每个数字保留一个代表视图 @@ -47,6 +50,7 @@ export const Book = defineComponent(props => { return Array.from(map.values()); }); + /** 将数值按大数规则格式化为展示字符串 */ const format = (value: number) => { return core.formatBigNumber(value); }; @@ -87,6 +91,7 @@ export const Book = defineComponent(props => { return first.value; }; + /** 拼接怪物全部特殊属性的名称,以空格分隔 */ const specialText = (base: IReadonlyEnemy) => { const names: string[] = []; for (const special of base.iterateSpecials()) { @@ -95,19 +100,22 @@ export const Book = defineComponent(props => { return names.join(' '); }; + /** 计算第 index 个数值列的中心横坐标 */ const statX = (index: number) => { return STAT_LEFT + (index * (MAIN_WIDTH - STAT_LEFT)) / 5; }; + /** 打开指定怪物视图的详细信息界面 */ const openDetail = (view: IEnemyView) => { props.controller.open(BookDetailUI, { enemy: view }); }; + /** 关闭当前怪物手册界面 */ const exit = () => props.controller.close(props.instance); return () => ( - + {/* 标题 */} (props => { font={nameFont} fillStyle="gold" /> + {/* 怪物列表区 */} {enemies.value.map((view, i) => { const base = view.getBaseEnemy(); @@ -144,6 +153,7 @@ export const Book = defineComponent(props => { font={statFont} fillStyle="#ffd27f" /> + {/* 数值列表区 */} (props => { font={statFont} fillStyle="lawngreen" /> - {critical !== null && ( + {/* 临界信息区 */} + {critical && ( (props => { fillStyle="#ffffff" /> )} - {critical !== null && ( + {critical && ( (props => { fillStyle="lightsalmon" /> )} - {critical !== null && ( + {critical && ( (props => { fillStyle="lightpink" /> )} - {critical !== null && def1 !== null && ( + {critical && def1 && ( (props => { ); })} + {/* 右下角退出按钮 */} (props => { ); }, bookProps); +/** 怪物手册列表的 UI 控制器 */ export const BookUI = new GameUI('book', Book); diff --git a/packages-user/client-modules/src/ui/bookDetail.tsx b/packages-user/client-modules/src/ui/bookDetail.tsx index e539cb8..26d63a6 100644 --- a/packages-user/client-modules/src/ui/bookDetail.tsx +++ b/packages-user/client-modules/src/ui/bookDetail.tsx @@ -2,8 +2,8 @@ import { GameUI, SetupComponentOptions } from '@motajs/system'; import { computed, defineComponent, ref } from 'vue'; import { Font } from '@motajs/render'; import { ITileLocator } from '@motajs/common'; -import { Scroll } from '@user/client-base'; -import { IEnemyCritical, IEnemyView } from '@user/data-system'; +import { Scroll, TextContent } from '@user/client-base'; +import { IEnemyCritical, IEnemyView, EnemyView } from '@user/data-system'; import { IEnemy, IReadonlyEnemy } from '@user/data-base'; import { IEnemyAttr } from '@user/data-common'; import { FULL_LOC, MAIN_HEIGHT, MAIN_WIDTH } from '../shared'; @@ -21,6 +21,7 @@ export interface BookDetailProps extends IUIPropsBase { enemy: IEnemy | IEnemyView; } +/** 怪物详情组件的 props 声明 */ const bookDetailProps = { props: ['controller', 'instance', 'state', 'enemy'] } satisfies SetupComponentOptions; @@ -32,21 +33,27 @@ const statFont = Font.defaults({ size: 15 }); /** 特殊属性字体 */ const specialFont = Font.defaults({ size: 14 }); +/** 怪物详细信息组件 */ export const BookDetail = defineComponent(props => { + /** 当前展示的属性模式 */ const mode = ref(DetailMode.Base); + /** 若入参为怪物视图则返回该视图,否则返回 null */ const getView = (): IEnemyView | null => { - if ('getBaseEnemy' in props.enemy) return props.enemy; + if (props.enemy instanceof EnemyView) return props.enemy; return null; }; + /** 获取基础属性,视图取基础怪物,否则取入参本身 */ const getBase = (): IReadonlyEnemy => { - if ('getBaseEnemy' in props.enemy) return props.enemy.getBaseEnemy(); + if (props.enemy instanceof EnemyView) return props.enemy.getBaseEnemy(); return props.enemy; }; + /** 获取计算后属性,视图走计算接口,否则取入参本身 */ const getComputed = (): IReadonlyEnemy => { - if ('getBaseEnemy' in props.enemy) return props.enemy.getComputedEnemy(); + if (props.enemy instanceof EnemyView) + return props.enemy.getComputedEnemy(); return props.enemy; }; @@ -57,6 +64,7 @@ export const BookDetail = defineComponent(props => { return view.context.getEnemyLocatorByView(view); }; + /** 当前模式对应的怪物数据 */ const current = computed(() => mode.value === DetailMode.Base ? getBase() : getComputed() ); @@ -85,20 +93,25 @@ export const BookDetail = defineComponent(props => { return first.done ? null : first.value; }); + /** 将数值按大数规则格式化为展示字符串 */ const format = (value: number) => core.formatBigNumber(value); + /** 计算第 index 个数值列的中心横坐标 */ const statX = (index: number) => 24 + (index * (MAIN_WIDTH - 48)) / 5; + /** 在基础属性与计算后属性之间切换 */ const toggleMode = () => { - if (!('getBaseEnemy' in props.enemy)) return; + if (!(props.enemy instanceof EnemyView)) return; mode.value = mode.value === DetailMode.Base ? DetailMode.Computed : DetailMode.Base; }; + /** 关闭当前怪物详情界面 */ const close = () => props.controller.close(props.instance); + /** 左下角切换按钮的显示文本 */ const toggleText = computed(() => mode.value === DetailMode.Base ? '切换至计算后属性' : '切换至基础属性' ); @@ -107,7 +120,7 @@ export const BookDetail = defineComponent(props => { const enemy = current.value; return ( - + {/* 标题 */} (props => { font={nameFont} fillStyle="gold" /> + {/* 属性数值区 */} (props => { font={statFont} fillStyle="lawngreen" /> + {/* 特殊属性列表区 */} {specials.value.map((special, i) => { const y = i * 44; @@ -165,10 +180,10 @@ export const BookDetail = defineComponent(props => { font={specialFont} fillStyle={special.getNameColor()} /> - @@ -183,7 +198,8 @@ export const BookDetail = defineComponent(props => { font={specialFont} fillStyle="#fffa9e" /> - {critical.value !== null && ( + {/* 临界信息区 */} + {critical.value && ( (props => { fillStyle="lightsalmon" /> )} - {critical.value !== null && ( + {critical.value && ( (props => { fillStyle="lightpink" /> )} + {/* 左下切换按钮 / 右下返回按钮 */} (props => { }; }, bookDetailProps); +/** 怪物详细信息的 UI 控制器 */ export const BookDetailUI = new GameUI('book-detail', BookDetail);