refactor(monster&cast): 重构怪物移动与AOE技能目标逻辑
1. 移除固定网格站位,怪物从右侧统一出生并向左推进 2. 修改AOE技能索敌逻辑,直接使用最近敌人真实位置 3. 新增怪物自动推进与战斗停船逻辑,优化战斗体验
This commit is contained in:
@@ -2,8 +2,7 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { FacSet } from "../common/config/GameSet";
|
||||
import { HeroDisVal, HType } from "../common/config/heroSet";
|
||||
import { BoxSet, FacSet } from "../common/config/GameSet";
|
||||
import { Node } from "cc";
|
||||
|
||||
@ecs.register('MonMoveComp')
|
||||
@@ -30,6 +29,8 @@ export class MonMoveComp extends ecs.Comp {
|
||||
|
||||
@ecs.register('MonMoveSystem')
|
||||
export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
/** 怪物接近英雄后的停船距离:小于该阈值即停下交战 */
|
||||
private readonly combatHaltDistance = 80;
|
||||
/** 渲染层级重排节流,避免每帧排序 */
|
||||
private readonly renderSortInterval = 0.05;
|
||||
private lastRenderSortAt = 0;
|
||||
@@ -81,25 +82,22 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
}
|
||||
|
||||
/** 所有移动都锁定在 baseY,避免出现“漂移” */
|
||||
// 注意:不再在 MonMoveComp 强行重置 X 轴坐标,避免与其他表现逻辑冲突
|
||||
if (view.node.position.y !== move.baseY) {
|
||||
view.node.setPosition(view.node.position.x, move.baseY, 0);
|
||||
}
|
||||
// 渲染层级统交由 MoveSystem 统一处理,避免两个 System 争抢 setSiblingIndex
|
||||
|
||||
// 仅在战斗中才处理索敌
|
||||
if (!smc.mission.in_fight) return;
|
||||
|
||||
const nearestEnemy = this.findNearestEnemy(e);
|
||||
// 仅在战斗中才处理索敌;非战斗阶段也允许向左推进,让怪物自然逼近英雄阵地
|
||||
const nearestEnemy = smc.mission.in_fight ? this.findNearestEnemy(e) : null;
|
||||
if (nearestEnemy) {
|
||||
/** 有敌人:进入固定位置攻击逻辑 */
|
||||
/** 有敌人:边移动边攻击 */
|
||||
this.processCombatLogic(e, move, view, model, nearestEnemy);
|
||||
this.syncCombatTarget(model, view, nearestEnemy);
|
||||
} else {
|
||||
/** 无敌人:原地待机 */
|
||||
/** 无敌人:清目标并继续向左推进 */
|
||||
this.clearCombatTarget(model);
|
||||
model.is_atking = false;
|
||||
view.status_change("idle");
|
||||
this.moveLeft(view, move, model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,17 +129,44 @@ export class MonMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
||||
private processCombatLogic(e: ecs.Entity, move: MonMoveComp, view: HeroViewComp, model: HeroAttrsComp, enemy: HeroViewComp) {
|
||||
const selfX = view.node.position.x;
|
||||
const enemyX = enemy.node.position.x;
|
||||
const inRange = this.isEnemyInAttackRange(model, selfX, enemyX);
|
||||
// 停船判定使用固定阈值(80),不依赖技能攻击范围
|
||||
const inRange = Math.abs(selfX - enemyX) <= this.combatHaltDistance;
|
||||
|
||||
// 攻击判定:怪物在固定位置,如果在攻击范围内则攻击,否则原地待机
|
||||
if (inRange) {
|
||||
// 接触到英雄方:停止移动,进入攻击状态,由 SCastSystem 负责技能释放
|
||||
model.is_atking = true;
|
||||
// 确保朝向敌人
|
||||
const dir = enemyX > selfX ? 1 : -1;
|
||||
view.scale = dir;
|
||||
if (view.status === "move") {
|
||||
view.status_change("idle");
|
||||
}
|
||||
} else {
|
||||
// 未接触:继续向左推进
|
||||
model.is_atking = false;
|
||||
view.status_change("idle");
|
||||
this.moveLeft(view, move, model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 持续向左推进:怪物不再固定站位,而是以 speed/3 的速度向左移动,
|
||||
* 直到抵达左边界(基地位置)后转入待机,由 SCastSystem 继续负责技能释放。
|
||||
*/
|
||||
private moveLeft(view: HeroViewComp, move: MonMoveComp, model: HeroAttrsComp) {
|
||||
const currentX = view.node.position.x;
|
||||
if (currentX <= BoxSet.LETF_END) {
|
||||
if (view.status !== "atk") {
|
||||
view.status_change("idle");
|
||||
}
|
||||
return;
|
||||
}
|
||||
const dir = -1;
|
||||
move.direction = dir;
|
||||
const speed = model.speed / 3;
|
||||
const delta = speed * this.dt * dir;
|
||||
const newX = Math.max(BoxSet.LETF_END, currentX + delta);
|
||||
if (Math.abs(newX - currentX) >= 0.01) {
|
||||
view.node.setPosition(newX, view.node.position.y, 0);
|
||||
view.status_change("move");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import { GameEvent } from "../common/config/GameEvent";
|
||||
import { SkillTriggerType } from "../common/config/heroSet";
|
||||
import { SkillTriggerHelper } from "./SkillTriggerHelper";
|
||||
import { MissionEconomy } from "../map/MissionEconomy";
|
||||
import { MissionMonCompComp } from "../map/MissionMonComp";
|
||||
import { MissionHeroComp } from "../map/MissionHeroComp";
|
||||
|
||||
/**
|
||||
@@ -695,25 +694,13 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
if (config.DTType === DTType.aoe_grid) {
|
||||
const isHero = heroAttrs.fac === FacSet.HERO;
|
||||
if (isHero) {
|
||||
// 英雄打怪物,目标为怪物网格的第2列(idx 1)中路(row 1)或第3列(idx 2)中路
|
||||
// MissionMonComp.MON_POSITIONS 顺序:
|
||||
// 列1: 0,1,2 (X=60)
|
||||
// 列2: 3,4,5 (X=140) -> 第2列中路是 index 4
|
||||
// 列3: 6,7,8 (X=220) -> 第3列中路是 index 7
|
||||
// 简单起见,可以固定取第2列中路(index 4)或第3列中路(index 7)
|
||||
// 若最近的敌人在更后排,也可以取那个敌人的列。
|
||||
// 需求:三类 需要以中路 第 2、 3列为目标。
|
||||
// 我们直接返回第2列中路坐标(X=140, Y=GAME_LINE)或者根据最近敌人判断。
|
||||
// 需求说明为第 2 或 第 3 列,这里我们可以根据目标位置,如果目标在第3列及以后,打第3列,否则打第2列。
|
||||
let targetCol = 1; // 0-based, so 1 is 2nd col
|
||||
if (nearestEnemy && nearestEnemy.node) {
|
||||
// 判断目标所在的列
|
||||
const ex = nearestEnemy.node.position.x;
|
||||
// X=60(列1), X=140(列2), X=220(列3), X=300(列4)
|
||||
if (ex >= 200) targetCol = 2; // 第3列
|
||||
// 怪物已改为从 X=400 出生后动态向左推进,不再有固定列阵型。
|
||||
// aoe_grid 直接以最近敌人的真实位置作为目标点,
|
||||
// 由技能自身的范围半径负责命中附近的怪物集群。
|
||||
if (nearestEnemy?.node) {
|
||||
return nearestEnemy.node.position.clone();
|
||||
}
|
||||
const targetIdx = targetCol * 3 + 1; // 1是中路
|
||||
return MissionMonCompComp.MON_POSITIONS[targetIdx].clone();
|
||||
return null;
|
||||
} else {
|
||||
// 怪物打英雄,英雄网格:
|
||||
// 列1: 0,1,2 (X=-210)
|
||||
|
||||
Reference in New Issue
Block a user