refactor: 合并英雄与怪物移动组件为通用 MoveComp
重构移动系统,将 HeroMoveComp 和 MonMoveComp 合并为通用的 MoveComp 组件,统一移动逻辑。 - 移除 HeroMasterComp 相关代码,简化实体查询 - 统一战斗范围计算和阵型回归逻辑 - 调整移动边界和撤退范围配置 - 优化敌人查找算法,提高性能
This commit is contained in:
@@ -186,49 +186,49 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
// 1. 基础近战型
|
||||
5201:{uuid:5201,name:"兽人战士",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10,
|
||||
type:HType.warrior,lv:1,hp:60,ap:8,speed:180,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"标准炮灰:确保英雄能完成3次普攻积累天赋计数"},
|
||||
// 2. 快速突击型
|
||||
5301:{uuid:5301,name:"兽人斥候",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:1.2,ss:10,
|
||||
type:HType.assassin,lv:1,hp:40,ap:12,speed:400,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"快速突击:极高移速贴脸,检测护盾(7102)刷新率"},
|
||||
// 3. 重型坦克型
|
||||
5401:{uuid:5401,name:"兽人卫士",icon:"1001",path:"mo3", fac:FacSet.MON, kind:1,as:5.0,ss:10,
|
||||
type:HType.warrior,lv:1,hp:200,ap:15,speed:60,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"重型坦克:数值墙,检测玩家破甲(7008)与持续输出"},
|
||||
|
||||
// 4. 远程骚扰型
|
||||
5501:{uuid:5501,name:"兽人射手",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10,
|
||||
type:HType.remote,lv:1,hp:50,ap:10,speed:90,skills:[6203],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"远程骚扰:跨屏打击,迫使阵地分散或移动英雄"},
|
||||
|
||||
// 5. 特殊机制型
|
||||
5601:{uuid:5601,name:"兽人自爆兵",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10,
|
||||
type:HType.assassin,lv:1,hp:80,ap:200,speed:220,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"特殊机制:极端伤害,漏怪即秒杀,检测减伤(7103)"},
|
||||
// 召唤师:持续召唤小怪(后续可在技能系统中实现 SType.zhaohuan)
|
||||
5602:{uuid:5602,name:"兽人召唤师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10,
|
||||
type:HType.mage,lv:1,hp:150,ap:10,speed:100,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"战术目标:持续召唤小怪,检测英雄大招清场频率"},
|
||||
// 治疗者:为周围怪物回血(此处以提升治疗效果和生命回复为基础被动)
|
||||
5603:{uuid:5603,name:"兽人祭司",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10,
|
||||
type:HType.support,lv:1,hp:150,ap:10,speed:105,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"战术目标:为怪群回血,检测玩家沉默(7006)覆盖率"},
|
||||
// 光环怪:为周围怪物提供增益(此处以Buff效果提升与移动速度提升为基础被动)
|
||||
// Attrs.BUFF_UP=60 (RATIO=1),Attrs.SPEED=63 (RATIO=1)
|
||||
5604:{uuid:5604,name:"兽人图腾师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10,
|
||||
type:HType.support,lv:1,hp:150,ap:10,speed:110,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"战术目标:提供加速光环,改变怪群推进节奏"},
|
||||
// 6. 精英/BOSS型
|
||||
5701:{uuid:5701,name:"兽人首领(BOSS)",icon:"1001",path:"mo4", fac:FacSet.MON, kind:1,as:2.5,ss:10,
|
||||
type:HType.warrior,lv:3,hp:2000,ap:60,speed:120,skills:[6003],
|
||||
rangeType: SkillRange.Long,
|
||||
rangeType: SkillRange.Melee,
|
||||
buff:[],info:"终极考验:极高HP,检测大招重置与辐射协同输出"},
|
||||
};
|
||||
|
||||
@@ -8,20 +8,19 @@ import { BoxSet, FacSet, FightSet, IndexSet } from "../common/config/GameSet";
|
||||
import { HeroInfo, HeroPos, HType } from "../common/config/heroSet";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { Attrs} from "../common/config/HeroAttrs";
|
||||
import { HeroMoveComp } from "./HeroMove";
|
||||
import { MoveComp } from "./MoveComp";
|
||||
import { mLogger } from "../common/Logger";
|
||||
import { HeroMasterComp } from "./HeroMasterComp";
|
||||
/** 角色实体 */
|
||||
@ecs.register(`Hero`)
|
||||
|
||||
export class Hero extends ecs.Entity {
|
||||
HeroModel!: HeroAttrsComp;
|
||||
View!: HeroViewComp;
|
||||
HeroMove!: HeroMoveComp;
|
||||
HeroMove!: MoveComp;
|
||||
debugMode: boolean = false; // 是否启用调试模式
|
||||
protected init() {
|
||||
this.addComponents<ecs.Comp>(
|
||||
HeroMoveComp,
|
||||
MoveComp,
|
||||
HeroAttrsComp,
|
||||
);
|
||||
}
|
||||
@@ -35,7 +34,6 @@ export class Hero extends ecs.Entity {
|
||||
|
||||
this.remove(HeroViewComp);
|
||||
this.remove(HeroAttrsComp);
|
||||
this.remove(HeroMasterComp)
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@@ -98,9 +96,10 @@ export class Hero extends ecs.Entity {
|
||||
model.back_chance=FightSet.BACK_CHANCE
|
||||
this.add(hv);
|
||||
oops.message.dispatchEvent(GameEvent.MasterCalled,{uuid:uuid})
|
||||
const move = this.get(HeroMoveComp);
|
||||
const move = this.get(MoveComp);
|
||||
move.direction = 1; // 向右移动
|
||||
move.targetX = 0; // 右边界'
|
||||
move.baseY = pos.y;
|
||||
if(HeroInfo[uuid].type==HType.remote){
|
||||
move.targetX = -100; // 右边界'
|
||||
}
|
||||
@@ -122,7 +121,7 @@ export class HeroLifecycleSystem extends ecs.ComblockSystem
|
||||
implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem {
|
||||
|
||||
filter() {
|
||||
return ecs.allOf(HeroMoveComp);
|
||||
return ecs.allOf(MoveComp);
|
||||
}
|
||||
|
||||
entityEnter(e: ecs.Entity): void {
|
||||
|
||||
@@ -8,14 +8,14 @@ import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { BuffConf, SkillSet } from "../common/config/SkillSet";
|
||||
import { getMonAttr, MonType } from "../map/RogueConfig";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { MonMoveComp } from "./MonMove";
|
||||
import { MoveComp } from "./MoveComp";
|
||||
import { mLogger } from "../common/Logger";
|
||||
/** 角色实体 */
|
||||
@ecs.register(`Monster`)
|
||||
export class Monster extends ecs.Entity {
|
||||
HeroModel!: HeroAttrsComp;
|
||||
HeroView!: HeroViewComp;
|
||||
MonMove!: MonMoveComp;
|
||||
MonMove!: MoveComp;
|
||||
private debugMode: boolean = false; // 是否启用调试模式
|
||||
|
||||
// 多键对象池:Map<prefabPath, NodePool>
|
||||
@@ -40,7 +40,7 @@ export class Monster extends ecs.Entity {
|
||||
|
||||
protected init() {
|
||||
this.addComponents<ecs.Comp>(
|
||||
MonMoveComp,
|
||||
MoveComp,
|
||||
HeroAttrsComp,
|
||||
);
|
||||
}
|
||||
@@ -135,10 +135,11 @@ export class Monster extends ecs.Entity {
|
||||
oops.message.dispatchEvent("monster_load",this)
|
||||
|
||||
// 初始化移动参数,包括线路和生成顺序
|
||||
const move = this.get(MonMoveComp);
|
||||
const move = this.get(MoveComp);
|
||||
move.reset();
|
||||
move.direction = -1; // 向左移动
|
||||
move.targetX = -800; // 左边界
|
||||
move.targetX = Math.max(-320, Math.min(320, pos.x));
|
||||
move.baseY = pos.y;
|
||||
move.lane = lane; // 设置线路标识
|
||||
move.spawnOrder = spawnOrder; // 设置生成顺序
|
||||
smc.vmdata.mission_data.mon_num++
|
||||
@@ -157,7 +158,7 @@ export class MonLifecycleSystem extends ecs.ComblockSystem
|
||||
debugMode: boolean = false; // 是否启用调试模式
|
||||
|
||||
filter() {
|
||||
return ecs.allOf(MonMoveComp);
|
||||
return ecs.allOf(MoveComp);
|
||||
}
|
||||
|
||||
entityEnter(e: ecs.Entity): void {
|
||||
|
||||
@@ -77,8 +77,9 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
// 战斗状态:根据职业类型和rangeType执行智能战术
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
} else {
|
||||
// 非战斗状态:向目标移动
|
||||
this.processMarchLogic(e, move, view, model);
|
||||
// 非战斗状态:回归阵型
|
||||
move.targetY = 0;
|
||||
this.processReturnFormation(e, move, view, model);
|
||||
model.is_atking = false;
|
||||
}
|
||||
}
|
||||
@@ -204,8 +205,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
/** 执行后撤逻辑 */
|
||||
private performRetreat(view: HeroViewComp, move: MonMoveComp, model: HeroAttrsComp, currentX: number) {
|
||||
const safeRetreatX = currentX - move.direction * 50;
|
||||
// 怪物活动范围通常宽一些
|
||||
if (safeRetreatX >= -450 && safeRetreatX <= 450) {
|
||||
if (safeRetreatX >= -300 && safeRetreatX <= 300) {
|
||||
const retreatSpeed = (model.speed / 3) * 0.8;
|
||||
this.moveEntity(view, -move.direction, retreatSpeed);
|
||||
model.is_atking = false;
|
||||
@@ -216,11 +216,8 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进军逻辑 (无敌人时)
|
||||
* 策略:向目标X移动 (通常是屏幕左侧)
|
||||
*/
|
||||
private processMarchLogic(e: ecs.Entity, move: MonMoveComp, view: HeroViewComp, model: HeroAttrsComp) {
|
||||
/** 回归阵型逻辑 */
|
||||
private processReturnFormation(e: ecs.Entity, move: MonMoveComp, view: HeroViewComp, model: HeroAttrsComp) {
|
||||
const currentX = view.node.position.x;
|
||||
const targetX = move.targetX;
|
||||
|
||||
@@ -228,7 +225,6 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
const dir = targetX > currentX ? 1 : -1;
|
||||
const speed = model.speed / 3;
|
||||
|
||||
// 修正朝向
|
||||
move.direction = dir;
|
||||
|
||||
this.moveEntity(view, dir, speed);
|
||||
@@ -255,7 +251,7 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
}
|
||||
|
||||
// 地图边界限制
|
||||
if (newX >= -450 && newX <= 450) {
|
||||
if (newX >= -320 && newX <= 320) {
|
||||
view.node.setPosition(newX, newY, 0);
|
||||
view.status_change("move");
|
||||
} else {
|
||||
|
||||
291
assets/script/game/hero/MoveComp.ts
Normal file
291
assets/script/game/hero/MoveComp.ts
Normal file
@@ -0,0 +1,291 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { FacSet } from "../common/config/GameSet";
|
||||
import { HType } from "../common/config/heroSet";
|
||||
import { SkillRange } from "../common/config/SkillSet";
|
||||
|
||||
@ecs.register('MoveComp')
|
||||
export class MoveComp extends ecs.Comp {
|
||||
direction: number = 1;
|
||||
targetX: number = 0;
|
||||
moving: boolean = true;
|
||||
targetY: number = 0;
|
||||
baseY: number = 0;
|
||||
lane: number = 0;
|
||||
spawnOrder: number = 0;
|
||||
|
||||
reset() {
|
||||
this.direction = 1;
|
||||
this.targetX = 0;
|
||||
this.moving = true;
|
||||
this.targetY = 0;
|
||||
this.baseY = 0;
|
||||
this.lane = 0;
|
||||
this.spawnOrder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
interface MoveFacConfig {
|
||||
moveMinX: number;
|
||||
moveMaxX: number;
|
||||
retreatMinX: number;
|
||||
retreatMaxX: number;
|
||||
}
|
||||
|
||||
@ecs.register('MoveSystem')
|
||||
export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
private readonly facConfigs: Record<number, MoveFacConfig> = {
|
||||
[FacSet.HERO]: {
|
||||
moveMinX: -320,
|
||||
moveMaxX: 320,
|
||||
retreatMinX: -300,
|
||||
retreatMaxX: 300,
|
||||
},
|
||||
[FacSet.MON]: {
|
||||
moveMinX: -320,
|
||||
moveMaxX: 320,
|
||||
retreatMinX: -300,
|
||||
retreatMaxX: 300,
|
||||
}
|
||||
};
|
||||
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(MoveComp, HeroViewComp, HeroAttrsComp);
|
||||
}
|
||||
|
||||
update(e: ecs.Entity) {
|
||||
if (!smc.mission.play || smc.mission.pause) return;
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const move = e.get(MoveComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!model || !move || !view || !view.node) return;
|
||||
if (model.fac !== FacSet.HERO && model.fac !== FacSet.MON) return;
|
||||
if (!move.moving) return;
|
||||
if (model.fac === FacSet.MON && smc.mission.stop_mon_action) {
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
if (model.is_stop || model.is_dead || model.is_reviving || model.in_stun || model.in_frost) {
|
||||
if (!model.is_reviving) view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateRenderOrder(e);
|
||||
const nearestEnemy = this.findNearestEnemy(e);
|
||||
if (nearestEnemy) {
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
} else {
|
||||
move.targetY = 0;
|
||||
this.processReturnFormation(e, move, view, model);
|
||||
model.is_atking = false;
|
||||
}
|
||||
}
|
||||
|
||||
private processCombatLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
let rangeType = model.rangeType;
|
||||
if (rangeType === undefined) {
|
||||
if (model.type === HType.warrior || model.type === HType.assassin) {
|
||||
rangeType = SkillRange.Melee;
|
||||
} else if (model.type === HType.remote) {
|
||||
rangeType = SkillRange.Long;
|
||||
} else {
|
||||
rangeType = SkillRange.Mid;
|
||||
}
|
||||
}
|
||||
|
||||
switch (rangeType) {
|
||||
case SkillRange.Melee:
|
||||
this.processMeleeLogic(e, move, view, model, enemy);
|
||||
break;
|
||||
case SkillRange.Mid:
|
||||
this.processMidLogic(e, move, view, model, enemy);
|
||||
break;
|
||||
case SkillRange.Long:
|
||||
this.processLongLogic(e, move, view, model, enemy);
|
||||
break;
|
||||
default:
|
||||
this.processMidLogic(e, move, view, model, enemy); // 默认中程
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private processMeleeLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const currentX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
const dist = Math.abs(currentX - enemyX);
|
||||
const [minRange, maxRange] = this.resolveCombatRange(model, 0, 75);
|
||||
|
||||
move.direction = enemyX > currentX ? 1 : -1;
|
||||
|
||||
if (dist < minRange) {
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist <= maxRange) {
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
} else {
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
}
|
||||
}
|
||||
|
||||
private processMidLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const currentX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
const dist = Math.abs(currentX - enemyX);
|
||||
|
||||
const [minRange, maxRange] = this.resolveCombatRange(model, 120, 360);
|
||||
|
||||
move.direction = enemyX > currentX ? 1 : -1;
|
||||
|
||||
if (dist < minRange) {
|
||||
// 太近了,后撤
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist > maxRange) {
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
}
|
||||
}
|
||||
|
||||
private processLongLogic(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const currentX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
const dist = Math.abs(currentX - enemyX);
|
||||
|
||||
const [minRange, maxRange] = this.resolveCombatRange(model, 360, 720);
|
||||
|
||||
move.direction = enemyX > currentX ? 1 : -1;
|
||||
|
||||
if (dist < minRange) {
|
||||
// 太近了,后撤 (远程单位对距离更敏感)
|
||||
this.performRetreat(view, move, model, currentX);
|
||||
} else if (dist > maxRange) {
|
||||
const speed = model.speed / 3;
|
||||
this.moveEntity(view, move.direction, speed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
}
|
||||
}
|
||||
|
||||
private performRetreat(view: HeroViewComp, move: MoveComp, model: HeroAttrsComp, currentX: number) {
|
||||
const cfg = this.facConfigs[model.fac] || this.facConfigs[FacSet.HERO];
|
||||
const safeRetreatX = currentX - move.direction * 50;
|
||||
if (safeRetreatX >= cfg.retreatMinX && safeRetreatX <= cfg.retreatMaxX) {
|
||||
const retreatSpeed = (model.speed / 3) * 0.8;
|
||||
this.moveEntity(view, -move.direction, retreatSpeed);
|
||||
model.is_atking = false;
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
model.is_atking = true;
|
||||
}
|
||||
}
|
||||
|
||||
private processReturnFormation(e: ecs.Entity, move: MoveComp, view: HeroViewComp, model: HeroAttrsComp) {
|
||||
const currentX = view.node.position.x;
|
||||
const targetX = this.getFixedFormationX(model);
|
||||
move.targetX = targetX;
|
||||
|
||||
if (Math.abs(currentX - targetX) > 5) {
|
||||
const dir = targetX > currentX ? 1 : -1;
|
||||
const speed = model.speed / 3;
|
||||
move.direction = dir;
|
||||
this.moveEntity(view, dir, speed);
|
||||
const newX = view.node.position.x;
|
||||
if ((dir === 1 && newX > targetX) || (dir === -1 && newX < targetX)) {
|
||||
view.node.setPosition(targetX, view.node.position.y, 0);
|
||||
}
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
}
|
||||
}
|
||||
|
||||
private getFixedFormationX(model: HeroAttrsComp): number {
|
||||
let rangeType = model.rangeType;
|
||||
if (rangeType === undefined || rangeType === null) {
|
||||
if (model.type === HType.remote) {
|
||||
rangeType = SkillRange.Long;
|
||||
} else if (model.type === HType.mage || model.type === HType.support) {
|
||||
rangeType = SkillRange.Mid;
|
||||
} else {
|
||||
rangeType = SkillRange.Melee;
|
||||
}
|
||||
}
|
||||
const side = model.fac === FacSet.MON ? 1 : -1;
|
||||
if (rangeType === SkillRange.Long) {
|
||||
return 240 * side;
|
||||
}
|
||||
if (rangeType === SkillRange.Mid) {
|
||||
return 200 * side;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private moveEntity(view: HeroViewComp, direction: number, speed: number) {
|
||||
const model = view.ent.get(HeroAttrsComp);
|
||||
const move = view.ent.get(MoveComp);
|
||||
if (!model || !move) return;
|
||||
const cfg = this.facConfigs[model.fac] || this.facConfigs[FacSet.HERO];
|
||||
const currentX = view.node.position.x;
|
||||
const delta = speed * this.dt * direction;
|
||||
let newX = view.node.position.x + delta;
|
||||
if (currentX < cfg.moveMinX && direction < 0) {
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
if (currentX > cfg.moveMaxX && direction > 0) {
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
newX = Math.max(cfg.moveMinX, Math.min(cfg.moveMaxX, newX));
|
||||
const newY = view.node.position.y;
|
||||
view.node.setPosition(newX, newY, 0);
|
||||
view.status_change("move");
|
||||
}
|
||||
|
||||
private resolveCombatRange(model: HeroAttrsComp, defaultMin: number, defaultMax: number): [number, number] {
|
||||
const minRange = model.getCachedMinSkillDistance();
|
||||
const maxRange = model.getCachedMaxSkillDistance();
|
||||
if (maxRange <= 0) return [defaultMin, defaultMax];
|
||||
const safeMin = Math.max(0, Math.min(minRange, maxRange - 20));
|
||||
return [safeMin, maxRange];
|
||||
}
|
||||
|
||||
private findNearestEnemy(entity: ecs.Entity): HeroViewComp | null {
|
||||
const currentView = entity.get(HeroViewComp);
|
||||
if (!currentView?.node) return null;
|
||||
|
||||
const currentPos = currentView.node.position;
|
||||
const myFac = entity.get(HeroAttrsComp).fac;
|
||||
|
||||
let nearest: HeroViewComp | null = null;
|
||||
let minDis = Infinity;
|
||||
|
||||
// 优化查询:一次遍历
|
||||
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => {
|
||||
const m = e.get(HeroAttrsComp);
|
||||
if (m.fac !== myFac && !m.is_dead) {
|
||||
const v = e.get(HeroViewComp);
|
||||
if (v?.node) {
|
||||
const d = Math.abs(currentPos.x - v.node.position.x);
|
||||
if (d < minDis) {
|
||||
minDis = d;
|
||||
nearest = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return nearest;
|
||||
}
|
||||
|
||||
private updateRenderOrder(entity: ecs.Entity) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
9
assets/script/game/hero/MoveComp.ts.meta
Normal file
9
assets/script/game/hero/MoveComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "836ec21a-d77d-4830-92bd-1e65887c5927",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import { CardType, FightSet, CardKind } from "../common/config/GameSet";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
|
||||
|
||||
import { HeroMasterComp } from "../hero/HeroMasterComp";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -252,16 +251,7 @@ export class MissionCardComp extends CCComp {
|
||||
*/
|
||||
fetchCards(level: number, forcedType?: CardType){
|
||||
// 获取主角已有的属性倾向 (已拥有的永久属性Buff)
|
||||
let preferredAttrs: number[] = [];
|
||||
// @ts-ignore
|
||||
const entities = ecs.query(ecs.allOf(HeroMasterComp));
|
||||
if (entities.length > 0) {
|
||||
const role = entities[0];
|
||||
const heroAttrs = role.get(HeroAttrsComp);
|
||||
if (heroAttrs && heroAttrs.BUFFS) {
|
||||
preferredAttrs = Object.keys(heroAttrs.BUFFS).map(Number);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 使用 CardSet 的 getCardOptions 获取卡牌
|
||||
// 这里我们要获取 4 张卡牌
|
||||
@@ -441,13 +431,10 @@ export class MissionCardComp extends CCComp {
|
||||
.to(0.1, { scale: new Vec3(1, 1, 1) })
|
||||
.delay(0.5)
|
||||
// .call(() => {
|
||||
// // 使用 HeroMasterComp 查找主角实体
|
||||
// // @ts-ignore
|
||||
// const entities = ecs.query(ecs.allOf(HeroMasterComp));
|
||||
// let role = entities.length > 0 ? entities[0] : null;
|
||||
|
||||
// if (!role) {
|
||||
// mLogger.log(this.debugMode, 'MissionCard', `[MissionCard] 未找到挂载 HeroMasterComp 的主角实体`);
|
||||
// } else {
|
||||
// mLogger.log(this.debugMode, 'MissionCard', `[MissionCard] 成功定位主角实体: ${role.eid}`);
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user