diff --git a/packages-user/client-modules/package.json b/packages-user/client-modules/package.json index 573de78..8810113 100644 --- a/packages-user/client-modules/package.json +++ b/packages-user/client-modules/package.json @@ -14,6 +14,7 @@ "@user/client-system": "workspace:*", "@user/data-common": "workspace:*", "@user/data-base": "workspace:*", + "@user/data-system": "workspace:*", "@user/data-state": "workspace:*" } } diff --git a/packages-user/data-state/__test__/mapScenario.perf.ts b/packages-user/data-state/__test__/mapScenario.perf.ts index 1a0cf2a..c5aabd8 100644 --- a/packages-user/data-state/__test__/mapScenario.perf.ts +++ b/packages-user/data-state/__test__/mapScenario.perf.ts @@ -677,7 +677,7 @@ describe('真实大地图战斗场景性能', () => { const record = measureCase('全图怪物单次临界计算', label, () => { for (const entry of fixture.state.enemyContext.iterateEnemy()) { const view = entry[1]; - for (const _critical of fixture.damageSystem.calculateCritical( + for (const _critical of fixture.damageSystem.calculateViewCritical( view, 'atk' )) { diff --git a/packages-user/data-state/src/enemy/calculator.ts b/packages-user/data-state/src/enemy/calculator.ts index d81c8e3..9948cf8 100644 --- a/packages-user/data-state/src/enemy/calculator.ts +++ b/packages-user/data-state/src/enemy/calculator.ts @@ -5,8 +5,8 @@ import { IReadonlyEnemyHandler } from '@user/data-system'; import { IEnemyAttr, IHeroAttr } from '@user/data-common'; -import { IVampireValue } from './special'; import { logger } from '@motajs/common'; +import { ISpecial9Value } from './special'; export class MainDamageCalculator implements IDamageCalculator< IEnemyAttr, @@ -51,7 +51,7 @@ export class MainDamageCalculator implements IDamageCalculator< } // 吸血 - const vampire = enemy.getSpecial(11); + const vampire = enemy.getSpecial(11); if (vampire) { const value = (vampire.value.vampire / 100) * hp; damage += value; diff --git a/packages-user/data-system/src/combat/__test__/damage.perf.ts b/packages-user/data-system/src/combat/__test__/damage.perf.ts index 423fff5..98db50f 100644 --- a/packages-user/data-system/src/combat/__test__/damage.perf.ts +++ b/packages-user/data-system/src/combat/__test__/damage.perf.ts @@ -253,7 +253,7 @@ describe('临界计算性能', () => { measureCase('临界计算', String(count), () => { for (let i = 0; i < count; i++) { - for (const _ of damageContext.calculateCritical( + for (const _ of damageContext.calculateViewCritical( fixture.view, 'atk' )) { @@ -275,7 +275,7 @@ describe('临界计算性能', () => { measureCase('临界计算', String(count), () => { for (let i = 0; i < count; i++) { - for (const _ of damageContext.calculateCritical( + for (const _ of damageContext.calculateViewCritical( fixture.view, 'atk' )) { @@ -297,7 +297,7 @@ describe('临界计算性能', () => { measureCase('临界计算', String(count), () => { for (let i = 0; i < count; i++) { - for (const _ of damageContext.calculateCritical( + for (const _ of damageContext.calculateViewCritical( fixture.view, 'atk' )) { diff --git a/packages-user/data-system/src/combat/__test__/damage.test.ts b/packages-user/data-system/src/combat/__test__/damage.test.ts index 6767f08..cf0c7f3 100644 --- a/packages-user/data-system/src/combat/__test__/damage.test.ts +++ b/packages-user/data-system/src/combat/__test__/damage.test.ts @@ -514,7 +514,7 @@ describe('DamageContext critical generation', () => { ); const first = context - .calculateCritical(fixture.view, 'atk') + .calculateViewCritical(fixture.view, 'atk') .next().value!; expect(first.baseValue).toBe(0); @@ -533,7 +533,7 @@ describe('DamageContext critical generation', () => { fixture.hero ); - const results = [...context.calculateCritical(fixture.view, 'atk')]; + const results = [...context.calculateViewCritical(fixture.view, 'atk')]; expect(results).toEqual([]); }); @@ -558,13 +558,16 @@ describe('DamageContext critical generation', () => { ); const heroResult = modules.logger.catch(() => [ - ...noHero.calculateCritical(fixture.view, 'atk') + ...noHero.calculateViewCritical(fixture.view, 'atk') ]); const calculatorResult = modules.logger.catch(() => [ - ...noCalculator.calculateCritical(fixture.view, 'atk') + ...noCalculator.calculateViewCritical(fixture.view, 'atk') ]); const locatorResult = modules.logger.catch(() => [ - ...withLocator.calculateCritical(createUnknownView(fixture), 'atk') + ...withLocator.calculateViewCritical( + createUnknownView(fixture), + 'atk' + ) ]); expect(heroResult.ret).toEqual([]); @@ -585,7 +588,7 @@ describe('DamageContext critical generation', () => { ); const first = context - .calculateCritical(fixture.view, 'atk') + .calculateViewCritical(fixture.view, 'atk') .next().value!; expect(first.nextValue).toBe(1); diff --git a/packages-user/data-system/src/combat/damage.ts b/packages-user/data-system/src/combat/damage.ts index 3d1ced0..0437997 100644 --- a/packages-user/data-system/src/combat/damage.ts +++ b/packages-user/data-system/src/combat/damage.ts @@ -10,7 +10,8 @@ import { IEnemyDamageInfo, IReadonlyEnemyHandler, IEnemyView, - IEnemyDamageInfoBase + IEnemyDamageInfoBase, + IReadonlyDamageHandler } from './types'; import { IHeroAttribute, @@ -57,9 +58,9 @@ export class DamageContext implements IDamageContext< */ private createReadonlyHandler( enemy: IReadonlyEnemy, - locator: ITileLocator, + locator: ITileLocator | null, hero: IReadonlyHeroAttribute - ): IReadonlyEnemyHandler { + ): IReadonlyDamageHandler { return { enemy, context: this.context, @@ -144,7 +145,7 @@ export class DamageContext implements IDamageContext< * @param maxIterations 最大迭代数量 */ private findNextCritical( - handler: IReadonlyEnemyHandler, + handler: IReadonlyDamageHandler, hero: IHeroAttribute, attribute: CriticalableHeroStatus, currentValue: number, @@ -181,7 +182,7 @@ export class DamageContext implements IDamageContext< }; } - *calculateCritical( + *calculateViewCritical( view: IEnemyView, attribute: CriticalableHeroStatus, precision: number = 12 @@ -196,9 +197,31 @@ export class DamageContext implements IDamageContext< } const locator = this.context.getEnemyLocatorByView(view); - if (!locator) return; - const enemy = view.getComputedEnemy(); + + yield* this.calculateEnemyCritical( + enemy, + attribute, + locator, + precision + ); + } + + *calculateEnemyCritical( + enemy: IReadonlyEnemy, + attribute: CriticalableHeroStatus, + locator: ITileLocator | null, + precision: number = 12 + ): Generator { + if (!this.heroStatus) { + logger.warn(107); + return; + } + if (!this.calculator) { + logger.warn(106); + return; + } + const hero = this.heroStatus.getModifiableClone(); const handler = this.createReadonlyHandler(enemy, locator, hero); diff --git a/packages-user/data-system/src/combat/types.ts b/packages-user/data-system/src/combat/types.ts index 38fffea..2b213ab 100644 --- a/packages-user/data-system/src/combat/types.ts +++ b/packages-user/data-system/src/combat/types.ts @@ -36,6 +36,20 @@ export interface IReadonlyEnemyHandler< readonly hero: IReadonlyHeroAttribute; } +export interface IReadonlyDamageHandler< + TEnemy, + THero +> extends IDataBaseExtended { + /** 怪物属性信息 */ + readonly enemy: IReadonlyEnemy; + /** 怪物上下文 */ + readonly context: IReadonlyEnemyContext; + /** 怪物定位符 */ + readonly locator: ITileLocator | null; + /** 勇士属性信息 */ + readonly hero: IReadonlyHeroAttribute; +} + //#endregion //#region 怪物对象 @@ -369,7 +383,7 @@ export interface IEnemyDamageInfoBase { export interface IEnemyDamageInfo extends IEnemyDamageInfoBase { /** 信息对象 */ - readonly handler: IReadonlyEnemyHandler; + readonly handler: IReadonlyDamageHandler; } export interface IEnemyCritical { @@ -397,7 +411,7 @@ export interface IDamageCalculator { * @param handler 信息对象 */ calculate( - handler: IReadonlyEnemyHandler + handler: IReadonlyDamageHandler ): IEnemyDamageInfoBase; /** @@ -406,7 +420,7 @@ export interface IDamageCalculator { * @param attribute 勇士的临界属性 */ getCriticalLimit( - handler: IReadonlyEnemyHandler, + handler: IReadonlyDamageHandler, attribute: CriticalableHeroStatus ): number; } @@ -442,11 +456,25 @@ export interface IDamageContext extends IDataBaseExtended { * @param attribute 计算临界的目标勇士属性,比如计算攻击临界、自定义属性的临界等等 * @param precision 临界计算精度,表示会进行多少次二分计算,一般填写 `12-16` 之间的数即可,默认是 12 */ - calculateCritical( + calculateViewCritical( enemy: IEnemyView, attribute: CriticalableHeroStatus, precision?: number ): Generator; + + /** + * 计算怪物在指定勇士属性下的临界 + * @param enemy 怪物只读对象 + * @param attribute 计算临界的目标勇士属性,比如计算攻击临界、自定义属性的临界等等 + * @param locator 怪物所在位置 + * @param precision 临界计算精度,表示会进行多少次二分计算,一般填写 `12-16` 之间的数即可,默认是 12 + */ + calculateEnemyCritical( + enemy: IReadonlyEnemy, + attribute: CriticalableHeroStatus, + locator: ITileLocator | null, + precision?: number + ): Generator; } export interface IDamageSystem extends IDamageContext< diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a5f43a..70a850f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,6 +461,9 @@ importers: '@user/data-state': specifier: workspace:* version: link:../data-state + '@user/data-system': + specifier: workspace:* + version: link:../data-system packages-user/client-system: dependencies: