fix(hero cast): 调整敌我单位的目标选择逻辑

重构了SCastSystem中的目标查找逻辑,区分英雄和怪物的目标选择规则:英雄仅按X轴距离选择最近目标,怪物优先选择中路目标后再比较距离,同时更新了对应注释说明。
This commit is contained in:
walkpan
2026-05-17 21:36:58 +08:00
parent a32eaf3bae
commit 048595887e

View File

@@ -549,7 +549,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const currentY = heroView.node.position.y; const currentY = heroView.node.position.y;
let nearest: HeroViewComp | null = null; let nearest: HeroViewComp | null = null;
let minDist = Infinity; let minDist = Infinity;
let foundSameLane = false; let foundPreferredLane = false;
const isHero = heroAttrs.fac === FacSet.HERO;
ecs.query(this.getHeroMatcher()).forEach(entity => { ecs.query(this.getHeroMatcher()).forEach(entity => {
const attrs = entity.get(HeroAttrsComp); const attrs = entity.get(HeroAttrsComp);
@@ -562,23 +563,29 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const distX = Math.abs(currentX - view.node.position.x); const distX = Math.abs(currentX - view.node.position.x);
if (distX > maxRange) return; if (distX > maxRange) return;
const isSameLane = Math.abs(currentY - view.node.position.y) < 30; // 30为容差 if (isHero) {
// 英雄单纯找X轴最近无视路线
if (distX < minDist) {
minDist = distX;
nearest = view;
}
} else {
// 怪物:优先找中路目标
const isMidLane = Math.abs(view.node.position.y) < 30; // 0 是中路
// 如果之前找到了同路目标,且当前不是同路,直接跳过 if (foundPreferredLane && !isMidLane) return;
if (foundSameLane && !isSameLane) return;
// 如果当前是同路,且之前没找到同路,则强制替换(同路优先) if (isMidLane && !foundPreferredLane) {
if (isSameLane && !foundSameLane) { foundPreferredLane = true;
foundSameLane = true; minDist = distX;
nearest = view;
return;
}
if (distX >= minDist) return;
minDist = distX; minDist = distX;
nearest = view; nearest = view;
return;
} }
// 同等路况下比较距离
if (distX >= minDist) return;
minDist = distX;
nearest = view;
}); });
return nearest; return nearest;
} }
@@ -586,7 +593,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
/** /**
* 在施法距离内查找“最前排”敌人。 * 在施法距离内查找“最前排”敌人。
* 依据施法者面向方向选择 x 轴上更前的目标。 * 依据施法者面向方向选择 x 轴上更前的目标。
* 考虑三路设计:同路优先 * 考虑三路设计:英雄找最前排,怪物优先找中路最前排
*/ */
private findFrontEnemyInRange(heroAttrs: HeroAttrsComp, heroView: HeroViewComp, maxRange: number, nearestEnemy: HeroViewComp): HeroViewComp | null { private findFrontEnemyInRange(heroAttrs: HeroAttrsComp, heroView: HeroViewComp, maxRange: number, nearestEnemy: HeroViewComp): HeroViewComp | null {
if (!heroView.node || !nearestEnemy.node) return null; if (!heroView.node || !nearestEnemy.node) return null;
@@ -595,7 +602,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const direction = nearestEnemy.node.position.x >= currentX ? 1 : -1; const direction = nearestEnemy.node.position.x >= currentX ? 1 : -1;
let frontEnemy: HeroViewComp | null = null; let frontEnemy: HeroViewComp | null = null;
let edgeX = direction > 0 ? Infinity : -Infinity; let edgeX = direction > 0 ? Infinity : -Infinity;
let foundSameLane = false; let foundPreferredLane = false;
const isHero = heroAttrs.fac === FacSet.HERO;
ecs.query(this.getHeroMatcher()).forEach(entity => { ecs.query(this.getHeroMatcher()).forEach(entity => {
const attrs = entity.get(HeroAttrsComp); const attrs = entity.get(HeroAttrsComp);
@@ -609,24 +617,38 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const dist = Math.abs(currentX - enemyX); const dist = Math.abs(currentX - enemyX);
if (dist > maxRange) return; if (dist > maxRange) return;
const isSameLane = Math.abs(currentY - view.node.position.y) < 30; if (isHero) {
if (foundSameLane && !isSameLane) return; // 英雄无视路线找X轴最前的
if (direction > 0) {
if (isSameLane && !foundSameLane) { if (enemyX >= edgeX) return;
foundSameLane = true; edgeX = enemyX;
edgeX = enemyX; } else {
if (enemyX <= edgeX) return;
edgeX = enemyX;
}
frontEnemy = view; frontEnemy = view;
return;
}
if (direction > 0) {
if (enemyX >= edgeX) return;
edgeX = enemyX;
} else { } else {
if (enemyX <= edgeX) return; // 怪物:优先找中路最前排的
edgeX = enemyX; const isMidLane = Math.abs(view.node.position.y) < 30;
if (foundPreferredLane && !isMidLane) return;
if (isMidLane && !foundPreferredLane) {
foundPreferredLane = true;
edgeX = enemyX;
frontEnemy = view;
return;
}
if (direction > 0) {
if (enemyX >= edgeX) return;
edgeX = enemyX;
} else {
if (enemyX <= edgeX) return;
edgeX = enemyX;
}
frontEnemy = view;
} }
frontEnemy = view;
}); });
return frontEnemy; return frontEnemy;
} }