From 24534fbca644a1a4543328896aa3749ddd3c41f2 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 15 Sep 2026 17:00:44 +0800 Subject: [PATCH] fix(07-01): #06-01-2 clear enemy-sourced map damage on delete - register viewStore/damageStore reverse indexes when sourced damage is written and re-register them after a refreshIndex recompute (route A) - deleteEnemy now finds and removes the enemy-sourced damage instead of leaving stale entries behind - un-skip the correct-expectation case in mapDamage.test.ts (#06-01-2) --- .../data-system/src/combat/mapDamage.test.ts | 4 +- .../data-system/src/combat/mapDamage.ts | 59 +++++++++++++++++-- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/packages-user/data-system/src/combat/mapDamage.test.ts b/packages-user/data-system/src/combat/mapDamage.test.ts index 889c0c4..e08b482 100644 --- a/packages-user/data-system/src/combat/mapDamage.test.ts +++ b/packages-user/data-system/src/combat/mapDamage.test.ts @@ -528,8 +528,8 @@ describe('MapDamage sourced conversion and reduction', () => { ]).toHaveLength(before); }); - // 疑似 bug:deleteEnemy 应移除该怪物带来的有来源地图伤害,详见 06-TEST-FINDINGS.md #06-01-2,修复后取消 skip - it.skip('removes enemy-sourced damage when the enemy is deleted', () => { + // 验证 deleteEnemy 会移除该怪物带来的有来源地图伤害 + it('removes enemy-sourced damage when the enemy is deleted', () => { const fixture = createFixture(); fixture.damage.useReducer(fixture.reducer); fixture.damage.useConverter(fixture.converter); diff --git a/packages-user/data-system/src/combat/mapDamage.ts b/packages-user/data-system/src/combat/mapDamage.ts index 6348e35..465f758 100644 --- a/packages-user/data-system/src/combat/mapDamage.ts +++ b/packages-user/data-system/src/combat/mapDamage.ts @@ -255,6 +255,35 @@ export class MapDamage implements IMapDamage { this.enemyStore.delete(view); } + /** + * 登记有来源伤害的反向索引,供删除与局部刷新时按来源清理 + * @param point 坐标点伤害信息 + * @param viewItem 产生伤害的视图 + * @param sourceEnemy 该视图所属的怪物视图 + * @param index 坐标索引 + * @param damage 该点上的伤害信息 + */ + private registerSourcedDamage( + point: IPointInfo, + viewItem: IMapDamageView, + sourceEnemy: IEnemyView, + index: number, + damage: Readonly + ): void { + point.affectedBy.add(viewItem); + point.damages.add(damage); + this.damageStore.set(damage, { + sourceView: viewItem, + sourceEnemy, + index + }); + const viewStore = this.viewStore.getOrInsertComputed(viewItem, () => ({ + damages: new Map(), + enemy: sourceEnemy + })); + viewStore.damages.set(index, damage); + } + /** * 刷新指定位置的怪物地图伤害,并执行刷新缓存的操作 */ @@ -286,8 +315,13 @@ export class MapDamage implements IMapDamage { ); const damage = viewItem.getDamageWithoutCheck(loc); if (damage) { - point.affectedBy.add(viewItem); - point.damages.add(damage); + this.registerSourcedDamage( + point, + viewItem, + view, + index, + damage + ); collection.add(index); } } @@ -325,8 +359,13 @@ export class MapDamage implements IMapDamage { ); const damage = viewItem.getDamageWithoutCheck(loc); if (damage) { - point.affectedBy.add(viewItem); - point.damages.add(damage); + this.registerSourcedDamage( + point, + viewItem, + view, + index, + damage + ); } } }); @@ -373,7 +412,17 @@ export class MapDamage implements IMapDamage { point.affectedBy.forEach(view => { const damage = view.getDamageWithoutCheck(locator); - if (damage) point.damages.add(damage); + if (!damage) return; + // 视图已被删除时不再重建其伤害,避免删除怪物后残留来源伤害 + const viewStore = this.viewStore.get(view); + if (!viewStore) return; + this.registerSourcedDamage( + point, + view, + viewStore.enemy, + index, + damage + ); }); } }