fix(技能系统): 修复远程技能目标选择逻辑,优先攻击最前方敌人

引入 DTType 判断,当技能为远程类型时,通过 findFrontEnemyInRange 方法筛选范围内最前方的敌人作为目标,而非最近的敌人。这确保了远程单位能正确攻击阵型前端的敌人,符合游戏战斗逻辑。
This commit is contained in:
walkpan
2026-03-19 20:48:15 +08:00
parent 916c82e936
commit 3c51db64fa

View File

@@ -2,7 +2,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
import { Vec3 } from "cc";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { BuffsList, SkillConfig, SkillKind, SkillSet, TGroup } from "../common/config/SkillSet";
import { BuffsList, DTType, SkillConfig, SkillKind, SkillSet, TGroup } from "../common/config/SkillSet";
import { Skill } from "../skill/Skill";
import { smc } from "../common/SingletonModuleComp";
import { GameConst } from "../common/config/GameConst";
@@ -76,7 +76,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
return { skillId: s_uuid, isFriendly: true, targetPos: null, targetEids: friendlyEids };
}
if (!target || !heroView.node || !target.node) continue;
const targetPos = this.buildEnemyCastTargetPos(heroView, target, maxRange);
const targetPos = this.resolveEnemyCastTargetPos(config, heroAttrs, heroView, target, maxRange);
if (!targetPos) continue;
return { skillId: s_uuid, isFriendly: false, targetPos, targetEids: [] };
}
return this.emptyCastPlan;
@@ -223,6 +224,42 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
return nearest;
}
private findFrontEnemyInRange(heroAttrs: HeroAttrsComp, heroView: HeroViewComp, maxRange: number, nearestEnemy: HeroViewComp): HeroViewComp | null {
if (!heroView.node || !nearestEnemy.node) return null;
const currentX = heroView.node.position.x;
const direction = nearestEnemy.node.position.x >= currentX ? 1 : -1;
let frontEnemy: HeroViewComp | null = null;
let edgeX = direction > 0 ? Infinity : -Infinity;
ecs.query(this.getHeroMatcher()).forEach(entity => {
const attrs = entity.get(HeroAttrsComp);
const view = entity.get(HeroViewComp);
if (!attrs || !view?.node) return;
if (attrs.fac === heroAttrs.fac) return;
if (attrs.is_dead || attrs.is_reviving) return;
const enemyX = view.node.position.x;
const dist = Math.abs(currentX - enemyX);
if (dist > maxRange) return;
if (direction > 0) {
if (enemyX >= edgeX) return;
edgeX = enemyX;
} else {
if (enemyX <= edgeX) return;
edgeX = enemyX;
}
frontEnemy = view;
});
return frontEnemy;
}
private resolveEnemyCastTargetPos(config: SkillConfig, heroAttrs: HeroAttrsComp, heroView: HeroViewComp, nearestEnemy: HeroViewComp, maxRange: number): Vec3 | null {
if (config.DTType !== DTType.range) {
return this.buildEnemyCastTargetPos(heroView, nearestEnemy, maxRange);
}
const frontEnemy = this.findFrontEnemyInRange(heroAttrs, heroView, maxRange, nearestEnemy);
if (!frontEnemy?.node) return null;
return frontEnemy.node.position.clone();
}
private resolveMaxCastRange(heroAttrs: HeroAttrsComp, type: HType): number {
const cached = heroAttrs.getCachedMaxSkillDistance();
if (cached > 0) return cached;