From 89936416e1bb26f75a803db81e4ab3d572ce68a0 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Thu, 16 Apr 2026 13:30:52 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages-user/data-base/src/enemy/context.ts | 91 +++++++++++++++++++- packages-user/data-base/src/enemy/types.ts | 2 +- packages-user/data-state/src/core.ts | 2 +- packages-user/data-state/src/enemy/final.ts | 12 +-- 4 files changed, 96 insertions(+), 11 deletions(-) diff --git a/packages-user/data-base/src/enemy/context.ts b/packages-user/data-base/src/enemy/context.ts index 63c9559..73ca631 100644 --- a/packages-user/data-base/src/enemy/context.ts +++ b/packages-user/data-base/src/enemy/context.ts @@ -67,16 +67,19 @@ export class EnemyContext implements IEnemyContext { this.width = width; this.height = height; this.indexer.setWidth(width); + this.needUpdate = true; } registerAuraConverter(converter: IAuraConverter): void { this.auraConverter.add(converter); this.converterStatus.set(converter, true); + this.needUpdate = true; } unregisterAuraConverter(converter: IAuraConverter): void { this.auraConverter.delete(converter); this.converterStatus.delete(converter); + this.needUpdate = true; } setAuraConverterEnabled( @@ -85,6 +88,7 @@ export class EnemyContext implements IEnemyContext { ): void { if (!this.auraConverter.has(converter)) return; this.converterStatus.set(converter, enabled); + this.needUpdate = true; } registerCommonQueryEffect( @@ -94,6 +98,7 @@ export class EnemyContext implements IEnemyContext { const array = this.commonQueryMap.getOrInsert(code, []); array.push(effect); array.sort((a, b) => b.priority - a.priority); + this.needUpdate = true; } unregisterCommonQueryEffect( @@ -105,11 +110,13 @@ export class EnemyContext implements IEnemyContext { const index = array.indexOf(effect); if (index === -1) return; array.splice(index, 1); + this.needUpdate = true; } registerSpecialQueryEffect(effect: IEnemySpecialQueryEffect): void { const list = this.specialQueryEffects.getOrInsert(effect.priority, []); list.push(effect); + this.needUpdate = true; } unregisterSpecialQueryEffect( @@ -124,11 +131,13 @@ export class EnemyContext implements IEnemyContext { if (list.length === 0) { this.specialQueryEffects.delete(effect.priority); } + this.needUpdate = true; } registerFinalEffect(effect: IEnemyFinalEffect): void { this.finalEffects.push(effect); this.finalEffects.sort((a, b) => b.priority - a.priority); + this.needUpdate = true; } unregisterFinalEffect(effect: IEnemyFinalEffect): void { @@ -136,6 +145,7 @@ export class EnemyContext implements IEnemyContext { if (index !== -1) { this.finalEffects.splice(index, 1); } + this.needUpdate = true; } getEnemyLocator(enemy: IEnemy): Readonly | null { @@ -166,6 +176,10 @@ export class EnemyContext implements IEnemyContext { return this.computedToView.get(enemy) ?? null; } + /** + * 删除指定索引位置的怪物以及与之关联的所有运行时状态。 + * @param index 地图索引 + */ private deleteEnemyAt(index: number) { const view = this.enemyViewMap.get(index); const enemy = this.enemyMap.get(index); @@ -201,6 +215,13 @@ export class EnemyContext implements IEnemyContext { this.locatorViewMap.set(view, index); this.computedToView.set(view.getComputingEnemy(), view); + if (this.mapDamage) { + this.mapDamage.markEnemyDirty(view); + } + if (this.damageSystem) { + this.damageSystem.markDirty(view); + } + this.needUpdate = true; } @@ -209,6 +230,11 @@ export class EnemyContext implements IEnemyContext { this.deleteEnemyAt(index); } + /** + * 在指定范围内筛选出当前上下文中的怪物视图。 + * @param range 范围对象 + * @param param 范围参数 + */ private *internalScanRange( range: IRange, param: T @@ -257,15 +283,23 @@ export class EnemyContext implements IEnemyContext { return this.mapDamage; } - attachDamageSystem(system: IDamageSystem): void { + attachDamageSystem(system: IDamageSystem | null): void { this.damageSystem = system; - system.markAllDirty(); + if (system) { + system.markAllDirty(); + } } getDamageSystem(): IDamageSystem | null { return this.damageSystem as IDamageSystem | null; } + /** + * 将怪物身上的特殊属性尝试转换为光环视图。 + * @param special 特殊属性 + * @param enemy 怪物对象 + * @param locator 怪物位置 + */ private convertSpecial( special: ISpecial, enemy: IReadonlyEnemy, @@ -288,6 +322,10 @@ export class EnemyContext implements IEnemyContext { return matched.convert(special, enemy, locator, this); } + /** + * 将光环按优先级插入到有序表中。 + * @param aura 光环视图 + */ private insertIntoSortedAura(aura: IAuraView): void { const set = this.sortedAura.getOrInsertComputed( aura.priority, @@ -296,6 +334,10 @@ export class EnemyContext implements IEnemyContext { set.add(aura); } + /** + * 从优先级表中移除一个光环。 + * @param aura 光环视图 + */ private removeFromSortedAura(aura: IAuraView): void { const set = this.sortedAura.get(aura.priority); if (set) { @@ -306,6 +348,13 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 执行特殊属性修饰器,并返回因此受到影响的光环集合。 + * @param modifier 特殊属性修饰器 + * @param enemy 目标怪物 + * @param locator 怪物位置 + * @param currentPriority 当前处理的优先级 + */ private processSpecialModifier( modifier: IEnemySpecialModifier, enemy: IEnemy, @@ -325,6 +374,7 @@ export class EnemyContext implements IEnemyContext { for (const adding of toAdd) { const aura = this.convertSpecial(adding, enemy, locator); if (aura) { + // 新生成的光环只能影响之后的阶段,不能反过来影响当前优先级链。 if (import.meta.env.DEV && aura.priority > currentPriority) { logger.warn( 99, @@ -344,6 +394,7 @@ export class EnemyContext implements IEnemyContext { enemy.deleteSpecial(deleting); const aura = this.convertedAura.get(deleting); if (aura) { + // 当前阶段不允许删除同优先级或更高优先级的已生效光环。 if (import.meta.env.DEV && aura.priority >= currentPriority) { logger.warn( 98, @@ -377,6 +428,11 @@ export class EnemyContext implements IEnemyContext { return affectedAuras; } + /** + * 执行单个特殊查询效果。 + * @param effect 特殊查询效果 + * @param currentPriority 当前处理的优先级 + */ private processSpecialQuery( effect: IEnemySpecialQueryEffect, currentPriority: number @@ -404,6 +460,11 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 执行光环带来的特殊属性修饰效果。 + * @param aura 光环视图 + * @param currentPriority 当前处理的优先级 + */ private processAuraSpecial( aura: IAuraView, currentPriority: number @@ -431,6 +492,9 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 构建所有由特殊属性衍生出的光环与特殊查询结果。 + */ private buildupSpecials(): void { for (const aura of this.globalAuraList) { this.insertIntoSortedAura(aura); @@ -450,6 +514,7 @@ export class EnemyContext implements IEnemyContext { const processedPriorities = new Set(); + // 由于期间可能会产生新优先级的光环,所以要用 while (true) 而不是直接遍历 while (true) { let maxPriority: number | null = null; for (const priority of this.sortedAura.keys()) { @@ -488,6 +553,9 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 按优先级执行所有基础属性光环效果。 + */ private buildupBase(): void { const priorities = [...this.sortedAura.keys()].sort((a, b) => b - a); for (const p of priorities) { @@ -505,6 +573,9 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 执行常规查询效果,并记录哪些怪物查询了上下文。 + */ private buildupQuery(): void { for (const [index, view] of this.enemyViewMap) { const enemy = view.getComputingEnemy(); @@ -527,6 +598,9 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 执行最终效果阶段。 + */ private buildupFinal(): void { for (const [index, view] of this.enemyViewMap) { const enemy = view.getComputingEnemy(); @@ -575,6 +649,12 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 在局部刷新期间执行特殊属性修饰器,但不重建光环拓扑。 + * @param modifier 特殊属性修饰器 + * @param enemy 目标怪物 + * @param locator 怪物位置 + */ private refreshSpecialModifier( modifier: IEnemySpecialModifier, enemy: IEnemy, @@ -619,6 +699,10 @@ export class EnemyContext implements IEnemyContext { } } + /** + * 刷新单个怪物视图的计算结果。 + * @param view 怪物视图 + */ private refreshEnemy(view: EnemyView): void { const locator = this.getEnemyLocatorByView(view); if (!locator) return; @@ -646,6 +730,7 @@ export class EnemyContext implements IEnemyContext { if (!aura.couldApplySpecial) continue; const param = aura.getRangeParam(); aura.range.bindHost(this); + // 局部刷新只重新判断“这个怪物是否被该光环命中”。 const inRange = aura.range.inRange( locator.x, locator.y, @@ -756,7 +841,7 @@ export class EnemyContext implements IEnemyContext { destroy(): void { this.clear(); this.attachMapDamage(null); - this.damageSystem = null; + this.attachDamageSystem(null); this.auraConverter.clear(); this.commonQueryMap.clear(); this.specialQueryEffects.clear(); diff --git a/packages-user/data-base/src/enemy/types.ts b/packages-user/data-base/src/enemy/types.ts index b08001b..2da3943 100644 --- a/packages-user/data-base/src/enemy/types.ts +++ b/packages-user/data-base/src/enemy/types.ts @@ -847,7 +847,7 @@ export interface IEnemyContext { * 绑定伤害计算系统 * @param system 伤害系统 */ - attachDamageSystem(system: IDamageSystem): void; + attachDamageSystem(system: IDamageSystem | null): void; /** * 获取当前绑定的伤害计算系统 diff --git a/packages-user/data-state/src/core.ts b/packages-user/data-state/src/core.ts index 4e7e306..4ede50e 100644 --- a/packages-user/data-state/src/core.ts +++ b/packages-user/data-state/src/core.ts @@ -76,7 +76,7 @@ export class CoreState implements ICoreState { loadState(data: IStateSaveData): void { this.hero.removeAllFollowers(); - data?.followers.forEach(v => { + data.followers.forEach(v => { this.hero.addFollower(v.num, v.identifier); }); } diff --git a/packages-user/data-state/src/enemy/final.ts b/packages-user/data-state/src/enemy/final.ts index 7c91d0c..4d97277 100644 --- a/packages-user/data-state/src/enemy/final.ts +++ b/packages-user/data-state/src/enemy/final.ts @@ -11,16 +11,16 @@ export class MainEnemyFinalEffect implements IEnemyFinalEffect readonly priority: number = 0; apply(enemy: IEnemy, _locator: ITileLocator): void { + // 3-坚固 if (enemy.hasSpecial(3)) { - enemy.setAttribute( - 'def', - Math.max( - enemy.getAttribute('def'), - HERO_STATUS_PLACEHOLDER.atk - 1 - ) + const target = Math.max( + enemy.getAttribute('def'), + HERO_STATUS_PLACEHOLDER.atk - 1 ); + enemy.setAttribute('def', target); } + // 10-模仿 if (enemy.hasSpecial(10)) { enemy.setAttribute('atk', HERO_STATUS_PLACEHOLDER.atk); enemy.setAttribute('def', HERO_STATUS_PLACEHOLDER.def);