diff --git a/packages-user/data-base/src/combat/context.ts b/packages-user/data-base/src/combat/context.ts index 165a7b9..2a6287f 100644 --- a/packages-user/data-base/src/combat/context.ts +++ b/packages-user/data-base/src/combat/context.ts @@ -18,66 +18,73 @@ import { IReadonlyHeroAttribute } from '../hero'; import { IEnemy, IReadonlyEnemy, ISpecial } from '../enemy'; import { EnemyView } from './enemy'; import { ILocationIndexer, MapLocIndexer } from '../common/indexer'; +import { IStateBase } from '../types'; -export class EnemyContext implements IEnemyContext { +export class EnemyContext implements IEnemyContext< + TEnemy, + THero +> { /** 坐标索引 -> 怪物视图 */ - private readonly enemyViewMap: Map> = new Map(); + private readonly enemyViewMap: Map> = new Map(); /** 坐标索引 -> 计算前怪物对象 */ - private readonly enemyMap: Map> = new Map(); + private readonly enemyMap: Map> = new Map(); /** 怪物视图 -> 坐标索引 */ - private readonly locatorViewMap: Map, number> = new Map(); + private readonly locatorViewMap: Map, number> = + new Map(); /** 计算前怪物对象 -> 坐标索引 */ - private readonly locatorEnemyMap: Map, number> = new Map(); + private readonly locatorEnemyMap: Map, number> = new Map(); /** 计算后怪物对象 -> 怪物视图 */ private readonly computedToView: Map< - IReadonlyEnemy, - EnemyView + IReadonlyEnemy, + EnemyView > = new Map(); /** 当前已注册的光环转换器 */ - private readonly auraConverter: Set> = + private readonly auraConverter: Set> = new Set(); /** 光环转换器是否启用 */ private readonly converterStatus: Map< - IAuraConverter, + IAuraConverter, boolean > = new Map(); /** 所有已被转换的光环 */ - private readonly convertedAura: Map, IAuraView> = + private readonly convertedAura: Map, IAuraView> = new Map(); /** 普通查询效果注册,特殊属性 -> 此特殊属性的查询效果列表,按照优先级从高到低排序 */ private readonly commonQueryMap: Map< number, - IEnemyCommonQueryEffect[] + IEnemyCommonQueryEffect[] > = new Map(); /** 特殊查询效果注册,特殊属性 -> 此特殊属性的特殊查询效果列表,按照优先级从高到低排序 */ private readonly specialQueryEffects: Map< number, - IEnemySpecialQueryEffect[] + IEnemySpecialQueryEffect[] > = new Map(); /** 最终效果列表,按照优先级从高到低排列 */ - private readonly finalEffects: IEnemyFinalEffect[] = []; + private readonly finalEffects: IEnemyFinalEffect[] = []; /** 添加的无来源全局光环列表 */ - private readonly globalAuraList: Set> = new Set(); + private readonly globalAuraList: Set> = new Set(); /** 排序后的光环视图,视图优先级 -> 光环视图列表 */ - private readonly sortedAura: Map>> = new Map(); + private readonly sortedAura: Map>> = + new Map(); /** 当怪物更新后,需要对上下文进行全量刷新的怪物列表 */ - private readonly needTotallyRefresh: Set> = new Set(); + private readonly needTotallyRefresh: Set> = new Set(); /** 所有实际查询了上下文的常规查询效果,这些怪物需要在上下文或其他怪物刷新时一并刷新 */ - private readonly requestedCommonContext: Set> = new Set(); + private readonly requestedCommonContext: Set> = + new Set(); /** 所有需要被标记为脏的怪物 */ - private readonly dirtyEnemy: Set> = new Set(); + private readonly dirtyEnemy: Set> = new Set(); /** 当前绑定的勇士属性对象 */ private bindedHero: IReadonlyHeroAttribute | null = null; /** 地图伤害对象 */ - private mapDamage: IMapDamage | null = null; + private mapDamage: IMapDamage | null = null; /** 伤害系统对象 */ - private damageSystem: IDamageSystem | null = null; + private damageSystem: IDamageSystem | null = null; /** 索引工具 */ readonly indexer: ILocationIndexer = new MapLocIndexer(); @@ -89,6 +96,8 @@ export class EnemyContext implements IEnemyContext { width: number = 0; height: number = 0; + constructor(readonly dataState: IStateBase) {} + resize(width: number, height: number): void { this.clear(); this.width = width; @@ -97,20 +106,20 @@ export class EnemyContext implements IEnemyContext { this.needUpdate = true; } - registerAuraConverter(converter: IAuraConverter): void { + registerAuraConverter(converter: IAuraConverter): void { this.auraConverter.add(converter); this.converterStatus.set(converter, true); this.needUpdate = true; } - unregisterAuraConverter(converter: IAuraConverter): void { + unregisterAuraConverter(converter: IAuraConverter): void { this.auraConverter.delete(converter); this.converterStatus.delete(converter); this.needUpdate = true; } setAuraConverterEnabled( - converter: IAuraConverter, + converter: IAuraConverter, enabled: boolean ): void { if (!this.auraConverter.has(converter)) return; @@ -120,7 +129,7 @@ export class EnemyContext implements IEnemyContext { registerCommonQueryEffect( code: number, - effect: IEnemyCommonQueryEffect + effect: IEnemyCommonQueryEffect ): void { const array = this.commonQueryMap.getOrInsert(code, []); array.push(effect); @@ -130,7 +139,7 @@ export class EnemyContext implements IEnemyContext { unregisterCommonQueryEffect( code: number, - effect: IEnemyCommonQueryEffect + effect: IEnemyCommonQueryEffect ): void { const array = this.commonQueryMap.get(code); if (!array) return; @@ -141,7 +150,7 @@ export class EnemyContext implements IEnemyContext { } registerSpecialQueryEffect( - effect: IEnemySpecialQueryEffect + effect: IEnemySpecialQueryEffect ): void { const list = this.specialQueryEffects.getOrInsert(effect.priority, []); list.push(effect); @@ -149,7 +158,7 @@ export class EnemyContext implements IEnemyContext { } unregisterSpecialQueryEffect( - effect: IEnemySpecialQueryEffect + effect: IEnemySpecialQueryEffect ): void { const list = this.specialQueryEffects.get(effect.priority); if (!list) return; @@ -163,13 +172,13 @@ export class EnemyContext implements IEnemyContext { this.needUpdate = true; } - registerFinalEffect(effect: IEnemyFinalEffect): void { + registerFinalEffect(effect: IEnemyFinalEffect): void { this.finalEffects.push(effect); this.finalEffects.sort((a, b) => b.priority - a.priority); this.needUpdate = true; } - unregisterFinalEffect(effect: IEnemyFinalEffect): void { + unregisterFinalEffect(effect: IEnemyFinalEffect): void { const index = this.finalEffects.indexOf(effect); if (index !== -1) { this.finalEffects.splice(index, 1); @@ -194,37 +203,39 @@ export class EnemyContext implements IEnemyContext { * @param locator 怪物位置 */ private createHandler( - enemy: IEnemy, + enemy: IEnemy, locator: ITileLocator - ): IEnemyHandler { - return { enemy, locator, hero: this.bindedHero! }; + ): IEnemyHandler { + return { enemy, locator, hero: this.bindedHero!, data: this.dataState }; } - getEnemyLocator(enemy: IEnemy): Readonly | null { + getEnemyLocator(enemy: IEnemy): Readonly | null { const index = this.locatorEnemyMap.get(enemy); if (index === undefined) return null; return this.indexer.indexToLocator(index); } getEnemyLocatorByView( - view: IEnemyView + view: IEnemyView ): Readonly | null { const index = this.locatorViewMap.get(view); if (index === undefined) return null; return this.indexer.indexToLocator(index); } - getEnemyByLocator(locator: ITileLocator): IEnemyView | null { + getEnemyByLocator(locator: ITileLocator): IEnemyView | null { const index = this.indexer.locToIndex(locator.x, locator.y); return this.enemyViewMap.get(index) ?? null; } - getEnemyByLoc(x: number, y: number): IEnemyView | null { + getEnemyByLoc(x: number, y: number): IEnemyView | null { const index = this.indexer.locToIndex(x, y); return this.enemyViewMap.get(index) ?? null; } - getViewByComputed(enemy: IReadonlyEnemy): IEnemyView | null { + getViewByComputed( + enemy: IReadonlyEnemy + ): IEnemyView | null { return this.computedToView.get(enemy) ?? null; } @@ -256,11 +267,11 @@ export class EnemyContext implements IEnemyContext { this.locatorEnemyMap.delete(enemy); } - setEnemyAt(locator: ITileLocator, enemy: IEnemy): void { + setEnemyAt(locator: ITileLocator, enemy: IEnemy): void { const index = this.indexer.locToIndex(locator.x, locator.y); this.deleteEnemyAt(index); - const view = new EnemyView(enemy, this); + const view = new EnemyView(enemy, this); this.enemyMap.set(index, enemy); this.enemyViewMap.set(index, view); this.locatorEnemyMap.set(enemy, index); @@ -290,7 +301,7 @@ export class EnemyContext implements IEnemyContext { private *internalScanRange( range: IRange, param: T - ): Iterable<[ITileLocator, EnemyView]> { + ): Iterable<[ITileLocator, EnemyView]> { range.bindHost(this); const keys = new Set(this.enemyViewMap.keys()); const matched = range.autoDetect(keys, param); @@ -307,46 +318,46 @@ export class EnemyContext implements IEnemyContext { scanRange( range: IRange, param: T - ): Iterable<[ITileLocator, IEnemyView]> { + ): Iterable<[ITileLocator, IEnemyView]> { return this.internalScanRange(range, param); } - *iterateEnemy(): Iterable<[ITileLocator, IEnemyView]> { + *iterateEnemy(): Iterable<[ITileLocator, IEnemyView]> { for (const [index, view] of this.enemyViewMap) { const locator = this.indexer.indexToLocator(index); yield [locator, view]; } } - addAura(aura: IAuraView): void { + addAura(aura: IAuraView): void { this.globalAuraList.add(aura); this.needUpdate = true; } - deleteAura(aura: IAuraView): void { + deleteAura(aura: IAuraView): void { this.globalAuraList.delete(aura); this.needUpdate = true; } - attachMapDamage(damage: IMapDamage | null): void { + attachMapDamage(damage: IMapDamage | null): void { this.mapDamage = damage; if (damage) { damage.refreshAll(); } } - getMapDamage(): IMapDamage | null { + getMapDamage(): IMapDamage | null { return this.mapDamage; } - attachDamageSystem(system: IDamageSystem | null): void { + attachDamageSystem(system: IDamageSystem | null): void { this.damageSystem = system; if (system) { system.bindHeroStatus(this.bindedHero); } } - getDamageSystem(): IDamageSystem | null { + getDamageSystem(): IDamageSystem | null { return this.damageSystem; } @@ -358,9 +369,9 @@ export class EnemyContext implements IEnemyContext { */ private convertSpecial( special: ISpecial, - handler: IReadonlyEnemyHandler - ): IEnemyAuraView | null { - let matched: IAuraConverter | null = null; + handler: IReadonlyEnemyHandler + ): IEnemyAuraView | null { + let matched: IAuraConverter | null = null; for (const converter of this.auraConverter) { if (!this.converterStatus.get(converter)) continue; if (converter.shouldConvert(special, handler)) { @@ -380,7 +391,7 @@ export class EnemyContext implements IEnemyContext { * 将光环按优先级插入到有序表中 * @param aura 光环视图 */ - private insertIntoSortedAura(aura: IAuraView): void { + private insertIntoSortedAura(aura: IAuraView): void { const set = this.sortedAura.getOrInsertComputed( aura.priority, () => new Set() @@ -392,7 +403,7 @@ export class EnemyContext implements IEnemyContext { * 从优先级表中移除一个光环 * @param aura 光环视图 */ - private removeFromSortedAura(aura: IAuraView): void { + private removeFromSortedAura(aura: IAuraView): void { const set = this.sortedAura.get(aura.priority); if (set) { set.delete(aura); @@ -410,12 +421,12 @@ export class EnemyContext implements IEnemyContext { * @param currentPriority 当前处理的优先级 */ private processSpecialModifier( - modifier: IEnemySpecialModifier, - handler: IEnemyHandler, + modifier: IEnemySpecialModifier, + handler: IEnemyHandler, currentPriority: number - ): Set> { + ): Set> { const enemy = handler.enemy; - const affectedAuras = new Set>(); + const affectedAuras = new Set>(); const toAdd = modifier.add(handler); const toDelete = modifier.delete(handler); @@ -487,7 +498,7 @@ export class EnemyContext implements IEnemyContext { * @param currentPriority 当前处理的优先级 */ private processSpecialQuery( - effect: IEnemySpecialQueryEffect, + effect: IEnemySpecialQueryEffect, currentPriority: number ): void { const modifier = effect.for(this); @@ -519,7 +530,7 @@ export class EnemyContext implements IEnemyContext { * @param currentPriority 当前处理的优先级 */ private processAuraSpecial( - aura: IAuraView, + aura: IAuraView, currentPriority: number ): void { const param = aura.getRangeParam(); @@ -694,7 +705,7 @@ export class EnemyContext implements IEnemyContext { } } - markDirty(view: IEnemyView): void { + markDirty(view: IEnemyView): void { if (!this.locatorViewMap.has(view)) return; this.dirtyEnemy.add(view); if (this.damageSystem) { @@ -709,8 +720,8 @@ export class EnemyContext implements IEnemyContext { * @param locator 怪物位置 */ private refreshSpecialModifier( - modifier: IEnemySpecialModifier, - handler: IEnemyHandler + modifier: IEnemySpecialModifier, + handler: IEnemyHandler ): void { const enemy = handler.enemy; const toAdd = modifier.add(handler); @@ -756,7 +767,7 @@ export class EnemyContext implements IEnemyContext { * 刷新单个怪物视图的计算结果 * @param view 怪物视图 */ - private refreshEnemy(view: EnemyView): void { + private refreshEnemy(view: EnemyView): void { const locator = this.getEnemyLocatorByView(view); if (!locator) return; @@ -851,7 +862,7 @@ export class EnemyContext implements IEnemyContext { } } - requestRefresh(view: IEnemyView): void { + requestRefresh(view: IEnemyView): void { if (!this.dirtyEnemy.has(view)) return; if (this.needTotallyRefresh.has(view)) { this.needUpdate = true; @@ -861,11 +872,11 @@ export class EnemyContext implements IEnemyContext { return; } - this.refreshEnemy(view as EnemyView); + this.refreshEnemy(view as EnemyView); for (const requestedView of this.requestedCommonContext) { if (requestedView === view) continue; - this.refreshEnemy(requestedView as EnemyView); + this.refreshEnemy(requestedView as EnemyView); } } diff --git a/packages-user/data-base/src/combat/damage.ts b/packages-user/data-base/src/combat/damage.ts index 10842af..ce70711 100644 --- a/packages-user/data-base/src/combat/damage.ts +++ b/packages-user/data-base/src/combat/damage.ts @@ -13,6 +13,7 @@ import { } from './types'; import { IHeroAttribute, IReadonlyHeroAttribute } from '../hero'; import { IReadonlyEnemy } from '../enemy'; +import { IStateBase } from '../types'; interface ICriticalSearchResult { /** 此临界点的属性值 */ @@ -21,20 +22,23 @@ interface ICriticalSearchResult { readonly info: IEnemyDamageInfo; } -export class DamageContext implements IDamageContext< - TAttr, +export class DamageContext implements IDamageContext< + TEnemy, THero > { /** 当前正在使用的计算器 */ - protected calculator: IDamageCalculator | null; + protected calculator: IDamageCalculator | null; /** 当前勇士属性 */ protected heroStatus: IReadonlyHeroAttribute | null; + readonly dataState: IStateBase; + constructor( - readonly context: IEnemyContext, - calculator: IDamageCalculator | null = null, + readonly context: IEnemyContext, + calculator: IDamageCalculator | null = null, heroStatus: IReadonlyHeroAttribute | null = null ) { + this.dataState = context.dataState; this.calculator = calculator; this.heroStatus = heroStatus; } @@ -46,14 +50,14 @@ export class DamageContext implements IDamageContext< * @param hero 勇士属性对象 */ private createReadonlyHandler( - enemy: IReadonlyEnemy, + enemy: IReadonlyEnemy, locator: ITileLocator, hero: IReadonlyHeroAttribute - ): IReadonlyEnemyHandler { - return { enemy, locator, hero }; + ): IReadonlyEnemyHandler { + return { enemy, locator, hero, data: this.dataState }; } - getDamageInfo(enemy: IEnemyView): IEnemyDamageInfo | null { + getDamageInfo(enemy: IEnemyView): IEnemyDamageInfo | null { if (!this.heroStatus) { logger.warn(107); return null; @@ -73,7 +77,7 @@ export class DamageContext implements IDamageContext< } getDamageInfoByComputed( - enemy: IReadonlyEnemy + enemy: IReadonlyEnemy ): IEnemyDamageInfo | null { if (!this.heroStatus) { logger.warn(107); @@ -96,7 +100,7 @@ export class DamageContext implements IDamageContext< } *calculateCritical( - view: IEnemyView, + view: IEnemyView, attribute: CriticalableHeroStatus, precision: number = 12 ): Generator { @@ -168,7 +172,7 @@ export class DamageContext implements IDamageContext< * @param maxIterations 最大迭代数量 */ private findNextCritical( - handler: IReadonlyEnemyHandler, + handler: IReadonlyEnemyHandler, hero: IHeroAttribute, attribute: CriticalableHeroStatus, currentValue: number, @@ -206,24 +210,24 @@ export class DamageContext implements IDamageContext< } } -export class DamageSystem - extends DamageContext - implements IDamageSystem +export class DamageSystem + extends DamageContext + implements IDamageSystem { /** 怪物伤害缓存 */ - private readonly cache: Map, IEnemyDamageInfo> = + private readonly cache: Map, IEnemyDamageInfo> = new Map(); - constructor(context: IEnemyContext) { + constructor(context: IEnemyContext) { super(context); } - useCalculator(calculator: IDamageCalculator): void { + useCalculator(calculator: IDamageCalculator): void { this.calculator = calculator; this.markAllDirty(); } - getCalculator(): IDamageCalculator | null { + getCalculator(): IDamageCalculator | null { return this.calculator; } @@ -232,7 +236,7 @@ export class DamageSystem this.markAllDirty(); } - getDamageInfo(enemy: IEnemyView): IEnemyDamageInfo | null { + getDamageInfo(enemy: IEnemyView): IEnemyDamageInfo | null { const cached = this.cache.get(enemy); if (cached) { return cached; @@ -246,7 +250,7 @@ export class DamageSystem } getDamageInfoByComputed( - enemy: IReadonlyEnemy + enemy: IReadonlyEnemy ): IEnemyDamageInfo | null { const view = this.context.getViewByComputed(enemy); if (view) { @@ -264,11 +268,11 @@ export class DamageSystem return info; } - markDirty(enemy: IEnemyView): void { + markDirty(enemy: IEnemyView): void { this.cache.delete(enemy); } - deleteEnemy(enemy: IEnemyView): void { + deleteEnemy(enemy: IEnemyView): void { this.cache.delete(enemy); } @@ -276,7 +280,7 @@ export class DamageSystem this.cache.clear(); } - with(hero: IHeroAttribute): IDamageContext { + with(hero: IHeroAttribute): IDamageContext { return new DamageContext(this.context, this.calculator, hero); } } diff --git a/packages-user/data-base/src/combat/mapDamage.ts b/packages-user/data-base/src/combat/mapDamage.ts index 5d3d576..2fd36e3 100644 --- a/packages-user/data-base/src/combat/mapDamage.ts +++ b/packages-user/data-base/src/combat/mapDamage.ts @@ -10,6 +10,7 @@ import { IMapDamageView } from './types'; import { ILocationHelper } from '../common/indexer'; +import { IStateBase } from '../types'; interface IPointInfo { /** 该点所有的地图伤害 */ @@ -34,9 +35,9 @@ interface IDamageStore { readonly index: number; } -export class MapDamage implements IMapDamage { +export class MapDamage implements IMapDamage { /** 当前使用的地图伤害转换器 */ - private converter: IMapDamageConverter | null = null; + private converter: IMapDamageConverter | null = null; /** 当前使用的地图伤害合并器 */ private reducer: IMapDamageReducer | null = null; @@ -45,14 +46,14 @@ export class MapDamage implements IMapDamage { /** 有来源地图伤害,坐标 -> 点伤害信息 */ private readonly sourcedDamage: Map = new Map(); /** 地图伤害视图 -> 其信息对象 */ - private readonly viewStore: Map, IViewStore> = + private readonly viewStore: Map, IViewStore> = new Map(); /** 地图伤害信息 -> 其信息对象 */ - private readonly damageStore: Map> = + private readonly damageStore: Map> = new Map(); /** 怪物视图 -> 其影响对象 */ private readonly enemyStore: Map< - IEnemyView, + IEnemyView, Set> > = new Map(); /** 需要延迟刷新的坐标索引 */ @@ -63,11 +64,14 @@ export class MapDamage implements IMapDamage { /** 坐标索引对象 */ private readonly indexer: ILocationHelper; - constructor(readonly context: IEnemyContext) { + readonly dataState: IStateBase; + + constructor(readonly context: IEnemyContext) { this.indexer = context.indexer; + this.dataState = context.dataState; } - useConverter(converter: IMapDamageConverter): void { + useConverter(converter: IMapDamageConverter): void { this.converter = converter; this.refreshAll(); } @@ -78,15 +82,16 @@ export class MapDamage implements IMapDamage { * @param locator 怪物位置 */ private createReadonlyHandler( - view: IEnemyView, + view: IEnemyView, locator: ITileLocator - ): IReadonlyEnemyHandler | null { + ): IReadonlyEnemyHandler | null { const hero = this.context.getBindedHero(); if (!hero) return null; return { enemy: view.getComputedEnemy(), locator, - hero + hero, + data: this.context.dataState }; } @@ -126,7 +131,7 @@ export class MapDamage implements IMapDamage { this.markDirtyIndex(this.indexer.locaterToIndex(locator)); } - markEnemyDirty(view: IEnemyView): void { + markEnemyDirty(view: IEnemyView): void { const store = this.enemyStore.get(view); const locator = this.context.getEnemyLocatorByView(view); if (!store) { @@ -141,7 +146,7 @@ export class MapDamage implements IMapDamage { this.refreshEnemyAndClearCache(view, locator); } - deleteEnemy(view: IEnemyView): void { + deleteEnemy(view: IEnemyView): void { const store = this.enemyStore.get(view); if (!store) return; const collection = new Set(); @@ -231,7 +236,7 @@ export class MapDamage implements IMapDamage { * 移除指定怪物所产生的地图伤害 * @param view 怪物视图 */ - private removeEnemyAffecting(view: IEnemyView) { + private removeEnemyAffecting(view: IEnemyView) { const views = this.enemyStore.get(view); if (!views) return; views.forEach(viewItem => { @@ -253,7 +258,7 @@ export class MapDamage implements IMapDamage { * 刷新指定位置的怪物地图伤害,并执行刷新缓存的操作 */ private refreshEnemyAndClearCache( - view: IEnemyView, + view: IEnemyView, locator: ITileLocator ) { this.removeEnemyAffecting(view); @@ -295,7 +300,7 @@ export class MapDamage implements IMapDamage { /** * 刷新指定位置的怪物地图伤害 */ - private refreshEnemy(view: IEnemyView, locator: ITileLocator) { + private refreshEnemy(view: IEnemyView, locator: ITileLocator) { this.removeEnemyAffecting(view); if (!this.converter) return; const handler = this.createReadonlyHandler(view, locator); diff --git a/packages-user/data-base/src/combat/types.ts b/packages-user/data-base/src/combat/types.ts index b3ae7f5..6f6b584 100644 --- a/packages-user/data-base/src/combat/types.ts +++ b/packages-user/data-base/src/combat/types.ts @@ -2,34 +2,39 @@ import { ITileLocator, IRange } from '@motajs/common'; import { IEnemy, IReadonlyEnemy, ISpecial } from '../enemy'; import { IReadonlyHeroAttribute, IHeroAttribute } from '../hero'; import { ILocationHelper } from '../common/indexer'; +import { IStateBase } from '../types'; //#region 辅助接口 -export interface IEnemyHandler { +export interface IEnemyHandler { /** 怪物属性信息 */ - readonly enemy: IEnemy; + readonly enemy: IEnemy; /** 怪物定位符 */ readonly locator: ITileLocator; /** 勇士属性信息 */ readonly hero: IReadonlyHeroAttribute; + /** 当前全局状态对象 */ + readonly data: IStateBase; } -export interface IReadonlyEnemyHandler { +export interface IReadonlyEnemyHandler { /** 怪物属性信息 */ - readonly enemy: IReadonlyEnemy; + readonly enemy: IReadonlyEnemy; /** 怪物定位符 */ readonly locator: ITileLocator; /** 勇士属性信息 */ readonly hero: IReadonlyHeroAttribute; + /** 当前全局状态对象 */ + readonly data: IStateBase; } //#endregion //#region 怪物对象 -export interface IEnemyView { +export interface IEnemyView { /** 怪物视图所属的上下文 */ - readonly context: IEnemyContext; + readonly context: IEnemyContext; /** * 重置此怪物视图的状态,将计算后怪物对象恢复至初始状态 @@ -39,18 +44,18 @@ export interface IEnemyView { /** * 获取基本怪物对象 */ - getBaseEnemy(): IReadonlyEnemy; + getBaseEnemy(): IReadonlyEnemy; /** * 获取计算后的怪物对象,返回的怪物对象同引用 */ - getComputedEnemy(): IReadonlyEnemy; + getComputedEnemy(): IReadonlyEnemy; /** * 获取可修改的怪物对象。如果修改此方法获取的怪物对象,那么怪物的真实信息是不会刷新的, * 需要手动调用 markDirty 方法来刷新。 */ - getModifiableEnemy(): IEnemy; + getModifiableEnemy(): IEnemy; /** * 将此怪物标记为脏,需要更新 @@ -62,18 +67,18 @@ export interface IEnemyView { //#region 光环与查询 -export interface IEnemySpecialModifier { +export interface IEnemySpecialModifier { /** * 获取要添加到指定怪物身上的特殊属性 * @param handler 信息对象 */ - add(handler: IReadonlyEnemyHandler): ISpecial[]; + add(handler: IReadonlyEnemyHandler): ISpecial[]; /** * 获取制定怪物身上要删除的特殊属性 * @param handler 信息对象 */ - delete(handler: IReadonlyEnemyHandler): ISpecial[]; + delete(handler: IReadonlyEnemyHandler): ISpecial[]; /** * 修改一个怪物的特殊属性,如果真正进行了修改则返回 true,否则返回 false @@ -81,16 +86,16 @@ export interface IEnemySpecialModifier { * @param special 要修改的怪物特殊属性 */ modify( - handler: IEnemyHandler, + handler: IEnemyHandler, special: ISpecial ): boolean; } -export interface IAuraView { +export interface IAuraView { /** 此光环视图的优先级 */ readonly priority: number; /** 此光环视图的影响范围 */ - readonly range: IRange; + readonly range: IRange; /** 这个光环视图是否有可能修改怪物的基本属性 */ readonly couldApplyBase: boolean; @@ -100,7 +105,7 @@ export interface IAuraView { /** * 获取范围扫描参数 */ - getRangeParam(): T; + getRangeParam(): TRange; /** * 对指定怪物对象施加修饰器 @@ -108,8 +113,8 @@ export interface IAuraView { * @param baseEnemy 原始怪物对象,即未进行任何修改的怪物对象 */ apply( - handler: IEnemyHandler, - baseEnemy: IReadonlyEnemy + handler: IEnemyHandler, + baseEnemy: IReadonlyEnemy ): void; /** @@ -118,21 +123,24 @@ export interface IAuraView { * @param baseEnemy 原始怪物对象,即未进行任何修改的怪物对象 */ applySpecial( - handler: IEnemyHandler, - baseEnemy: IReadonlyEnemy - ): IEnemySpecialModifier | null; + handler: IEnemyHandler, + baseEnemy: IReadonlyEnemy + ): IEnemySpecialModifier | null; } -export interface IEnemyAuraView extends IAuraView { +export interface IEnemyAuraView extends IAuraView< + TEnemy, + TRange +> { /** 此光环视图所属的怪物 */ - readonly enemy: IReadonlyEnemy; + readonly enemy: IReadonlyEnemy; /** 此光环视图所属的特殊属性 */ - readonly special: ISpecial; + readonly special: ISpecial; /** 此光环视图所属怪物的定位符 */ readonly locator: ITileLocator; } -export interface IAuraConverter { +export interface IAuraConverter { /** * 判断一个特殊属性是否应该被当前光环转换器执行转换 * @param special 要转换的特殊属性 @@ -140,7 +148,7 @@ export interface IAuraConverter { */ shouldConvert( special: ISpecial, - handler: IReadonlyEnemyHandler + handler: IReadonlyEnemyHandler ): boolean; /** @@ -148,22 +156,22 @@ export interface IAuraConverter { */ convert( special: ISpecial, - handler: IReadonlyEnemyHandler, - context: IEnemyContext - ): IEnemyAuraView; + handler: IReadonlyEnemyHandler, + context: IEnemyContext + ): IEnemyAuraView; } export interface IEnemySpecialQueryModifier< - TAttr, + TEnemy, THero -> extends IEnemySpecialModifier { +> extends IEnemySpecialModifier { /** * 判断一个怪物是否应该查询外部状态 */ - shouldQuery(handler: IReadonlyEnemyHandler): boolean; + shouldQuery(handler: IReadonlyEnemyHandler): boolean; } -export interface IEnemySpecialQueryEffect { +export interface IEnemySpecialQueryEffect { /** 效果优先级,与光环属性共用 */ readonly priority: number; @@ -171,11 +179,11 @@ export interface IEnemySpecialQueryEffect { * 根据传入的怪物上下文,获取对应的怪物特殊属性修饰器 */ for( - ctx: IEnemyContext - ): IEnemySpecialQueryModifier; + ctx: IEnemyContext + ): IEnemySpecialQueryModifier; } -export interface IEnemyCommonQueryEffect { +export interface IEnemyCommonQueryEffect { /** 优先级,越高的越先执行 */ readonly priority: number; @@ -183,20 +191,20 @@ export interface IEnemyCommonQueryEffect { * 对怪物的某个特殊属性施加常规查询效果 */ apply( - handler: IEnemyHandler, + handler: IEnemyHandler, special: ISpecial, - query: () => IEnemyContext + query: () => IEnemyContext ): void; } -export interface IEnemyFinalEffect { +export interface IEnemyFinalEffect { /** 效果优先级,越高会越先被执行 */ readonly priority: number; /** * 向怪物施加最终修饰效果 */ - apply(handler: IEnemyHandler): void; + apply(handler: IEnemyHandler): void; } //#endregion @@ -245,13 +253,13 @@ export interface IMapDamageView { ): Readonly | null; } -export interface IMapDamageConverter { +export interface IMapDamageConverter { /** * 转换地图伤害视图 */ convert( - handler: IReadonlyEnemyHandler, - context: IEnemyContext + handler: IReadonlyEnemyHandler, + context: IEnemyContext ): IMapDamageView[]; } @@ -265,15 +273,17 @@ export interface IMapDamageReducer { ): Readonly; } -export interface IMapDamage { +export interface IMapDamage { /** 当前绑定的怪物上下文 */ - readonly context: IEnemyContext; + readonly context: IEnemyContext; + /** 地图伤害系统绑定的全局状态对象 */ + readonly dataState: IStateBase; /** * 设置地图伤害转换器,并基于当前上下文重建所有地图伤害视图 * @param converter 地图伤害转换器 */ - useConverter(converter: IMapDamageConverter): void; + useConverter(converter: IMapDamageConverter): void; /** * 设置地图伤害合并器 @@ -305,7 +315,7 @@ export interface IMapDamage { * 将指定怪物对应的地图伤害标记为脏并刷新 * @param view 怪物视图 */ - markEnemyDirty(view: IEnemyView): void; + markEnemyDirty(view: IEnemyView): void; /** * 基于当前上下文重新刷新全部有来源地图伤害 @@ -316,7 +326,7 @@ export interface IMapDamage { * 删除指定怪物带来的全部地图伤害来源 * @param view 怪物视图 */ - deleteEnemy(view: IEnemyView): void; + deleteEnemy(view: IEnemyView): void; /** * 获取指定位置合并后的地图伤害 @@ -363,12 +373,12 @@ export type CriticalableHeroStatus = keyof { [P in keyof THero as THero[P] extends number ? P : never]: number; }; -export interface IDamageCalculator { +export interface IDamageCalculator { /** * 计算战斗伤害信息 * @param handler 信息对象 */ - calculate(handler: IReadonlyEnemyHandler): IEnemyDamageInfo; + calculate(handler: IReadonlyEnemyHandler): IEnemyDamageInfo; /** * 获取临界计算的上界 @@ -376,24 +386,27 @@ export interface IDamageCalculator { * @param attribute 勇士的临界属性 */ getCriticalLimit( - handler: IReadonlyEnemyHandler, + handler: IReadonlyEnemyHandler, attribute: CriticalableHeroStatus ): number; } -export interface IDamageContext { +export interface IDamageContext { + /** 伤害上下文所属的全局状态对象 */ + readonly dataState: IStateBase; + /** * 获取战斗伤害信息 * @param enemy 怪物视图 */ - getDamageInfo(enemy: IEnemyView): IEnemyDamageInfo | null; + getDamageInfo(enemy: IEnemyView): IEnemyDamageInfo | null; /** * 根据怪物对象获取战斗伤害信息 * @param enemy 怪物对象 */ getDamageInfoByComputed( - enemy: IReadonlyEnemy + enemy: IReadonlyEnemy ): IEnemyDamageInfo | null; /** @@ -403,29 +416,29 @@ export interface IDamageContext { * @param precision 临界计算精度,表示会进行多少次二分计算,一般填写 `12-16` 之间的数即可,默认是 12 */ calculateCritical( - enemy: IEnemyView, + enemy: IEnemyView, attribute: CriticalableHeroStatus, precision?: number ): Generator; } -export interface IDamageSystem extends IDamageContext< - TAttr, +export interface IDamageSystem extends IDamageContext< + TEnemy, THero > { /** 伤害系统所属的上下文 */ - readonly context: IEnemyContext; + readonly context: IEnemyContext; /** * 设置当前伤害计算系统使用的伤害计算器 * @param calculator 伤害计算器 */ - useCalculator(calculator: IDamageCalculator): void; + useCalculator(calculator: IDamageCalculator): void; /** * 获取当前使用的伤害计算器 */ - getCalculator(): IDamageCalculator | null; + getCalculator(): IDamageCalculator | null; /** * 绑定勇士信息 @@ -437,13 +450,13 @@ export interface IDamageSystem extends IDamageContext< * 将指定的怪物标记为脏 * @param enemy 怪物视图 */ - markDirty(enemy: IEnemyView): void; + markDirty(enemy: IEnemyView): void; /** * 删除指定的怪物 * @param enemy 怪物视图 */ - deleteEnemy(enemy: IEnemyView): void; + deleteEnemy(enemy: IEnemyView): void; /** * 将所有怪物标记为脏 @@ -454,20 +467,22 @@ export interface IDamageSystem extends IDamageContext< * 修改勇士属性,然后返回修改后勇士属性所组成的计算对象,不影响当前伤害系统的状态 * @param modify 勇士修改函数 */ - with(hero: IHeroAttribute): IDamageContext; + with(hero: IHeroAttribute): IDamageContext; } //#endregion //#region 上下文 -export interface IEnemyContext { +export interface IEnemyContext { /** 怪物上下文宽度 */ readonly width: number; /** 怪物上下文高度 */ readonly height: number; /** 此上下文使用的索引对象 */ readonly indexer: ILocationHelper; + /** 当前怪物上下文绑定的全局状态对象 */ + readonly dataState: IStateBase; /** * 调整上下文尺寸,并清空当前上下文中的所有怪物与状态 @@ -480,13 +495,13 @@ export interface IEnemyContext { * 注册一个光环转换器 * @param converter 光环转换器 */ - registerAuraConverter(converter: IAuraConverter): void; + registerAuraConverter(converter: IAuraConverter): void; /** * 注销一个光环转换器 * @param converter 光环转换器 */ - unregisterAuraConverter(converter: IAuraConverter): void; + unregisterAuraConverter(converter: IAuraConverter): void; /** * 设置光环转换器的启用状态 @@ -494,7 +509,7 @@ export interface IEnemyContext { * @param enabled 是否启用 */ setAuraConverterEnabled( - converter: IAuraConverter, + converter: IAuraConverter, enabled: boolean ): void; @@ -503,7 +518,7 @@ export interface IEnemyContext { * @param effect 特殊属性查询效果 */ registerSpecialQueryEffect( - effect: IEnemySpecialQueryEffect + effect: IEnemySpecialQueryEffect ): void; /** @@ -511,7 +526,7 @@ export interface IEnemyContext { * @param effect 特殊属性查询效果 */ unregisterSpecialQueryEffect( - effect: IEnemySpecialQueryEffect + effect: IEnemySpecialQueryEffect ): void; /** @@ -521,7 +536,7 @@ export interface IEnemyContext { */ registerCommonQueryEffect( code: number, - effect: IEnemyCommonQueryEffect + effect: IEnemyCommonQueryEffect ): void; /** @@ -531,20 +546,20 @@ export interface IEnemyContext { */ unregisterCommonQueryEffect( code: number, - effect: IEnemyCommonQueryEffect + effect: IEnemyCommonQueryEffect ): void; /** * 注册一个最终效果 * @param effect 最终效果 */ - registerFinalEffect(effect: IEnemyFinalEffect): void; + registerFinalEffect(effect: IEnemyFinalEffect): void; /** * 注销一个最终效果 * @param effect 最终效果 */ - unregisterFinalEffect(effect: IEnemyFinalEffect): void; + unregisterFinalEffect(effect: IEnemyFinalEffect): void; /** * 绑定勇士对象 @@ -561,41 +576,41 @@ export interface IEnemyContext { * 获取指定怪物对象当前所在位置 * @param enemy 怪物对象 */ - getEnemyLocator(enemy: IEnemy): Readonly | null; + getEnemyLocator(enemy: IEnemy): Readonly | null; /** * 获取指定怪物视图当前所在位置 * @param view 怪物视图 */ getEnemyLocatorByView( - view: IEnemyView + view: IEnemyView ): Readonly | null; /** * 根据定位符获取怪物视图 * @param locator 地图定位符 */ - getEnemyByLocator(locator: ITileLocator): IEnemyView | null; + getEnemyByLocator(locator: ITileLocator): IEnemyView | null; /** * 根据坐标获取怪物视图 * @param x 横坐标 * @param y 纵坐标 */ - getEnemyByLoc(x: number, y: number): IEnemyView | null; + getEnemyByLoc(x: number, y: number): IEnemyView | null; /** * 根据计算后怪物对象反查怪物视图 * @param enemy 计算后怪物对象 */ - getViewByComputed(enemy: IReadonlyEnemy): IEnemyView | null; + getViewByComputed(enemy: IReadonlyEnemy): IEnemyView | null; /** * 在指定位置放置一个怪物对象 * @param locator 地图定位符 * @param enemy 怪物对象 */ - setEnemyAt(locator: ITileLocator, enemy: IEnemy): void; + setEnemyAt(locator: ITileLocator, enemy: IEnemy): void; /** * 删除指定位置的怪物 @@ -611,46 +626,46 @@ export interface IEnemyContext { scanRange( range: IRange, param: T - ): Iterable<[ITileLocator, IEnemyView]>; + ): Iterable<[ITileLocator, IEnemyView]>; /** * 迭代上下文中的全部怪物 */ - iterateEnemy(): Iterable<[ITileLocator, IEnemyView]>; + iterateEnemy(): Iterable<[ITileLocator, IEnemyView]>; /** * 添加一个全局光环视图 * @param aura 光环视图 */ - addAura(aura: IAuraView): void; + addAura(aura: IAuraView): void; /** * 删除一个全局光环视图 * @param aura 光环视图 */ - deleteAura(aura: IAuraView): void; + deleteAura(aura: IAuraView): void; /** * 绑定地图伤害管理器 * @param damage 地图伤害管理器 */ - attachMapDamage(damage: IMapDamage | null): void; + attachMapDamage(damage: IMapDamage | null): void; /** * 获取当前绑定的地图伤害管理器 */ - getMapDamage(): IMapDamage | null; + getMapDamage(): IMapDamage | null; /** * 绑定伤害计算系统 * @param system 伤害系统 */ - attachDamageSystem(system: IDamageSystem | null): void; + attachDamageSystem(system: IDamageSystem | null): void; /** * 获取当前绑定的伤害计算系统 */ - getDamageSystem(): IDamageSystem | null; + getDamageSystem(): IDamageSystem | null; /** * 重建当前上下文中的全部怪物计算结果 @@ -666,13 +681,13 @@ export interface IEnemyContext { * 将指定怪物视图标记为脏 * @param view 怪物视图 */ - markDirty(view: IEnemyView): void; + markDirty(view: IEnemyView): void; /** * 申请刷新指定怪物视图 * @param view 怪物视图 */ - requestRefresh(view: IEnemyView): void; + requestRefresh(view: IEnemyView): void; /** * 清空当前上下文中的所有对象与运行状态 diff --git a/packages-user/data-base/src/enemy/enemy.ts b/packages-user/data-base/src/enemy/enemy.ts index 36a0fd0..369ae39 100644 --- a/packages-user/data-base/src/enemy/enemy.ts +++ b/packages-user/data-base/src/enemy/enemy.ts @@ -1,6 +1,6 @@ import { logger } from '@motajs/common'; +import { SaveCompression } from '../common'; import { IEnemy, IEnemySaveState, IReadonlyEnemy, ISpecial } from './types'; -import { SaveCompression } from '../common/types'; export class Enemy implements IEnemy { /** 怪物身上的特殊属性列表 */ diff --git a/packages-user/data-base/src/enemy/special.ts b/packages-user/data-base/src/enemy/special.ts index 59c1083..6f53661 100644 --- a/packages-user/data-base/src/enemy/special.ts +++ b/packages-user/data-base/src/enemy/special.ts @@ -1,5 +1,5 @@ import { isEqual } from 'lodash-es'; -import { SaveCompression } from '../common/types'; +import { SaveCompression } from '../common'; import { ISpecial, SpecialCreation } from './types'; // TODO: 颜色参数 diff --git a/packages-user/data-base/src/enemy/types.ts b/packages-user/data-base/src/enemy/types.ts index 94251ad..61d6ba8 100644 --- a/packages-user/data-base/src/enemy/types.ts +++ b/packages-user/data-base/src/enemy/types.ts @@ -1,4 +1,4 @@ -import { ISaveableContent } from '../common/types'; +import { ISaveableContent } from '../common'; //#region 怪物基础