refactor(hero): 统一英雄攻击射程配置并优化射程判断
1. 将MoveSystem和MonMoveSystem中的硬编码射程常量替换为HeroDisVal统一配置 2. 调整近战英雄默认攻击射程为120,修正原硬编码数值不一致问题 3. 优化施法射程计算逻辑,复用HeroDisVal配置 4. 为敌人查找逻辑添加同路优先筛选逻辑 5. 修正部分英雄技能的弹道类型为贝塞尔曲线 6. 移除冗余的射程常量定义,统一配置管理
This commit is contained in:
@@ -193,7 +193,7 @@ export const SkillSet: Record<number, SkillConfig> = {
|
||||
6001: {
|
||||
uuid:6001,name:t("skill_name_6001"),sp_name:"atk",icon:"1026",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
|
||||
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.Melee,
|
||||
RType:RType.linear,EType:EType.collision,buffs:[],info:t("skill_info_6001", 1, 100),
|
||||
RType:RType.bezier,EType:EType.collision,buffs:[],info:t("skill_info_6001", 1, 100),
|
||||
},
|
||||
6002: {
|
||||
uuid:6002,name:t("skill_name_6002"),sp_name:"ball_fire",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
|
||||
@@ -208,7 +208,7 @@ export const SkillSet: Record<number, SkillConfig> = {
|
||||
6004: {
|
||||
uuid:6004,name:t("skill_name_6004"),sp_name:"ball_zi",icon:"1126",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
|
||||
DTType:DTType.single,ap:100,hit_count:1,hitcd:0.3,speed:720,with:90,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
|
||||
RType:RType.linear,EType:EType.collision,buffs:[],info:t("skill_info_6004", 1, 100),
|
||||
RType:RType.bezier,EType:EType.collision,buffs:[],info:t("skill_info_6004", 1, 100),
|
||||
},
|
||||
6005: {
|
||||
uuid:6005,name:t("skill_name_6005"),sp_name:"arrow",icon:"1135",TGroup:TGroup.Enemy,readyAnm:"",endAnm:"",act:"atk",
|
||||
@@ -248,7 +248,7 @@ export const SkillSet: Record<number, SkillConfig> = {
|
||||
6104: {
|
||||
uuid:6104,name:t("skill_name_6104"),sp_name:"arrow_big_yellow",icon:"1135",TGroup:TGroup.Enemy,readyAnm:"yellow",endAnm:"",act:"max",
|
||||
DTType:DTType.single,crt:20,ap:100,hit_count:6,hitcd:0.2,speed:720,with:0,ready:0.2,EAnm:0,DAnm:"",IType:IType.remote,
|
||||
RType:RType.linear,EType:EType.collision,buffs:[],info:t("skill_info_6104", 6, 100),
|
||||
RType:RType.bezier,EType:EType.collision,buffs:[],info:t("skill_info_6104", 6, 100),
|
||||
},
|
||||
6105: {
|
||||
uuid:6105,name:t("skill_name_6105"),sp_name:"atk_fire",icon:"1173",TGroup:TGroup.Enemy,readyAnm:"blues",endAnm:"",act:"max",
|
||||
|
||||
@@ -69,7 +69,7 @@ export const FormationPointX = {
|
||||
} as const;
|
||||
|
||||
export const HeroDisVal: Record<HType.Melee | HType.Mid | HType.Long, number> = {
|
||||
[HType.Melee]: 720,
|
||||
[HType.Melee]: 120,
|
||||
[HType.Mid]: 720,
|
||||
[HType.Long]: 720,
|
||||
}
|
||||
@@ -207,7 +207,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
6001:{uuid:6001,name:t("mon_name_6001"),path:"mo1", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,hp:120,ap:12,speed:100,
|
||||
skills:{6001:{uuid:6001,lv:1,cd:0.65,ccd:0}},info:""},
|
||||
6002:{uuid:6002,name:t("mon_name_6002"),path:"mo3", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,hp:120,ap:12,speed:100,
|
||||
skills:{6001:{uuid:6001,lv:1,cd:0.65,ccd:0},6004:{uuid:6004,lv:1,cd:10,ccd:0}},info:""},
|
||||
skills:{6001:{uuid:6001,lv:1,cd:0.65,ccd:0}},info:""},
|
||||
6003:{uuid:6003,name:t("mon_name_6003"),path:"mo4", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,hp:350,ap:30,speed:100,
|
||||
skills:{6001:{uuid:6001,lv:1,cd:2,ccd:0}},info:""},
|
||||
// 4. 远程
|
||||
@@ -217,7 +217,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
skills:{6001:{uuid:6203,lv:1,cd:1.5,ccd:0}},info:""},
|
||||
// 6. 精英/BOSS型
|
||||
6006:{uuid:6006,name:t("mon_name_6006"),path:"mo6", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,hp:1500,ap:20,speed:100,
|
||||
skills:{6002:{uuid:6002,lv:1,cd:2,ccd:0},6004:{uuid:6004,lv:1,cd:10,ccd:0}},info:""},
|
||||
skills:{6002:{uuid:6002,lv:1,cd:2,ccd:0}},info:""},
|
||||
//============== 亡灵系列 ===============
|
||||
// 近战型
|
||||
6101:{uuid:6101,name:t("mon_name_6101"),path:"mud1", fac:FacSet.MON,cards_lv:1,lv:1,type:HType.Melee,hp:120,ap:12,speed:100,
|
||||
|
||||
@@ -30,10 +30,6 @@ export class MonMoveComp extends ecs.Comp {
|
||||
|
||||
@ecs.register('MonMoveSystem')
|
||||
export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
/** 近战判定射程 */
|
||||
private readonly meleeAttackRange = 250;
|
||||
/** 远程判定射程 */
|
||||
private readonly longAttackRange = 600;
|
||||
/** 渲染层级重排节流,避免每帧排序 */
|
||||
private readonly renderSortInterval = 0.05;
|
||||
private lastRenderSortAt = 0;
|
||||
@@ -128,8 +124,8 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
private isEnemyInAttackRange(model: HeroAttrsComp, selfX: number, enemyX: number): boolean {
|
||||
const dist = Math.abs(selfX - enemyX);
|
||||
const rangeType = model.type as HType.Melee | HType.Mid | HType.Long;
|
||||
if (rangeType === HType.Melee) return dist <= this.meleeAttackRange;
|
||||
return dist <= this.longAttackRange;
|
||||
const attackRange = HeroDisVal[rangeType];
|
||||
return dist <= attackRange;
|
||||
}
|
||||
|
||||
private processCombatLogic(e: ecs.Entity, move: MonMoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
|
||||
@@ -48,10 +48,6 @@ interface MoveFacConfig {
|
||||
|
||||
@ecs.register('MoveSystem')
|
||||
export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
/** 近战判定射程 */
|
||||
private readonly meleeAttackRange = 250;
|
||||
/** 远程判定射程 */
|
||||
private readonly longAttackRange = 600;
|
||||
private readonly heroFrontAnchorX = -100;
|
||||
private readonly monFrontAnchorX = 0;
|
||||
/** 常规同阵营横向最小间距(英雄) */
|
||||
@@ -166,8 +162,8 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
private isEnemyInAttackRange(model: HeroAttrsComp, selfX: number, enemyX: number): boolean {
|
||||
const dist = Math.abs(selfX - enemyX);
|
||||
const rangeType = model.type as HType.Melee | HType.Mid | HType.Long;
|
||||
if (rangeType === HType.Melee) return dist <= this.meleeAttackRange;
|
||||
return dist <= this.longAttackRange;
|
||||
const attackRange = HeroDisVal[rangeType];
|
||||
return dist <= attackRange;
|
||||
}
|
||||
|
||||
private processCombatLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { HeroViewComp } from "./HeroViewComp";
|
||||
import { DTType, RType, SkillConfig, SkillKind, SkillSet, SkillUpList, TGroup } from "../common/config/SkillSet";
|
||||
import { Skill } from "../skill/Skill";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { HeroInfo, HType } from "../common/config/heroSet";
|
||||
import { HeroDisVal, HeroInfo, HType } from "../common/config/heroSet";
|
||||
import { Attrs } from "../common/config/HeroAttrs";
|
||||
import { BoxSet, FacSet, FightSet } from "../common/config/GameSet";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
@@ -140,8 +140,6 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
}
|
||||
/** 空施法计划:用于“当前无可施法技能”时的统一返回 */
|
||||
private readonly emptyCastPlan = { skillId: 0, skillLv: 1, isFriendly: false, targetPos: null as Vec3 | null, targetEids: [] as number[] };
|
||||
/** 近战英雄默认施法射程 */
|
||||
private readonly meleeCastRange = 64;
|
||||
/** 查询缓存:避免每帧重复创建 matcher */
|
||||
private heroMatcher: ecs.IMatcher | null = null;
|
||||
|
||||
@@ -543,12 +541,16 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
/**
|
||||
* 在施法距离内查找最近敌人。
|
||||
* 用于单体技能与基础目标参考。
|
||||
* 考虑三路设计:同路(Y差较小)优先,如果同路没有目标再考虑跨路
|
||||
*/
|
||||
private findNearestEnemyInRange(heroAttrs: HeroAttrsComp, heroView: HeroViewComp, maxRange: number): HeroViewComp | null {
|
||||
if (!heroView.node) return null;
|
||||
const currentX = heroView.node.position.x;
|
||||
const currentY = heroView.node.position.y;
|
||||
let nearest: HeroViewComp | null = null;
|
||||
let minDist = Infinity;
|
||||
let foundSameLane = false;
|
||||
|
||||
ecs.query(this.getHeroMatcher()).forEach(entity => {
|
||||
const attrs = entity.get(HeroAttrsComp);
|
||||
const view = entity.get(HeroViewComp);
|
||||
@@ -556,10 +558,26 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (attrs.fac === heroAttrs.fac) return;
|
||||
if (attrs.is_dead || attrs.is_reviving) return;
|
||||
if (this.isOutOfBattleBounds(view.node.position.x)) return;
|
||||
const dist = Math.abs(currentX - view.node.position.x);
|
||||
if (dist > maxRange) return;
|
||||
if (dist >= minDist) return;
|
||||
minDist = dist;
|
||||
|
||||
const distX = Math.abs(currentX - view.node.position.x);
|
||||
if (distX > maxRange) return;
|
||||
|
||||
const isSameLane = Math.abs(currentY - view.node.position.y) < 30; // 30为容差
|
||||
|
||||
// 如果之前找到了同路目标,且当前不是同路,直接跳过
|
||||
if (foundSameLane && !isSameLane) return;
|
||||
|
||||
// 如果当前是同路,且之前没找到同路,则强制替换(同路优先)
|
||||
if (isSameLane && !foundSameLane) {
|
||||
foundSameLane = true;
|
||||
minDist = distX;
|
||||
nearest = view;
|
||||
return;
|
||||
}
|
||||
|
||||
// 同等路况下比较距离
|
||||
if (distX >= minDist) return;
|
||||
minDist = distX;
|
||||
nearest = view;
|
||||
});
|
||||
return nearest;
|
||||
@@ -568,13 +586,17 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
/**
|
||||
* 在施法距离内查找“最前排”敌人。
|
||||
* 依据施法者面向方向选择 x 轴上更前的目标。
|
||||
* 考虑三路设计:同路优先
|
||||
*/
|
||||
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 currentY = heroView.node.position.y;
|
||||
const direction = nearestEnemy.node.position.x >= currentX ? 1 : -1;
|
||||
let frontEnemy: HeroViewComp | null = null;
|
||||
let edgeX = direction > 0 ? Infinity : -Infinity;
|
||||
let foundSameLane = false;
|
||||
|
||||
ecs.query(this.getHeroMatcher()).forEach(entity => {
|
||||
const attrs = entity.get(HeroAttrsComp);
|
||||
const view = entity.get(HeroViewComp);
|
||||
@@ -583,8 +605,20 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (attrs.is_dead || attrs.is_reviving) return;
|
||||
const enemyX = view.node.position.x;
|
||||
if (this.isOutOfBattleBounds(enemyX)) return;
|
||||
|
||||
const dist = Math.abs(currentX - enemyX);
|
||||
if (dist > maxRange) return;
|
||||
|
||||
const isSameLane = Math.abs(currentY - view.node.position.y) < 30;
|
||||
if (foundSameLane && !isSameLane) return;
|
||||
|
||||
if (isSameLane && !foundSameLane) {
|
||||
foundSameLane = true;
|
||||
edgeX = enemyX;
|
||||
frontEnemy = view;
|
||||
return;
|
||||
}
|
||||
|
||||
if (direction > 0) {
|
||||
if (enemyX >= edgeX) return;
|
||||
edgeX = enemyX;
|
||||
@@ -618,9 +652,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
private resolveMaxCastRange(heroAttrs: HeroAttrsComp, type: HType): number {
|
||||
const cached = heroAttrs.getCachedMaxSkillDistance();
|
||||
if (cached > 0) return cached;
|
||||
if (type === HType.Long) return 720;
|
||||
if (type === HType.Mid) return 360;
|
||||
return this.meleeCastRange;
|
||||
const rangeType = type as HType.Melee | HType.Mid | HType.Long;
|
||||
return HeroDisVal[rangeType];
|
||||
}
|
||||
|
||||
/** 生成沿目标方向的施法目标坐标 */
|
||||
|
||||
Reference in New Issue
Block a user