feat(skill): 重构技能系统,新增技能数据组件和移动组件
refactor(skill): 移除旧技能组件和文档,优化技能配置结构 fix(skill): 修正技能预制体配置错误,统一技能运行类型字段 docs(skill): 删除过时的技能系统说明文档 perf(skill): 优化技能加载逻辑,减少资源消耗 style(skill): 调整代码格式,提高可读性
This commit is contained in:
149
assets/script/game/hero/SCastSystem.ts
Normal file
149
assets/script/game/hero/SCastSystem.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { Vec3, v3 } from "cc";
|
||||
import { CastSkillRequestComp } from "./STagComps";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { SkillSet, SType } from "../common/config/SkillSet";
|
||||
import { SkillEnt } from "../skill/SkillEnt";
|
||||
import { HeroSkillsComp } from "./HeroSkills";
|
||||
|
||||
/**
|
||||
* ==================== 技能施法系统 ====================
|
||||
*
|
||||
* 职责:
|
||||
* 1. 监听 CastSkillRequestComp 标记组件
|
||||
* 2. 检查施法条件(CD、MP、状态)
|
||||
* 3. 扣除资源(MP)
|
||||
* 4. 创建技能实体
|
||||
* 5. 触发施法动画
|
||||
* 6. 移除请求标记
|
||||
*
|
||||
* 设计理念:
|
||||
* - 使用标记组件驱动,符合 ECS 理念
|
||||
* - 施法检查与执行分离
|
||||
* - 自动处理资源消耗和CD重置
|
||||
*/
|
||||
@ecs.register('SkillCastSystem')
|
||||
export class SkillCastSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
|
||||
|
||||
/**
|
||||
* 过滤器:拥有技能数据 + 施法请求的实体
|
||||
*/
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(HeroSkillsComp, HeroAttrsComp, CastSkillRequestComp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体进入时触发(即请求施法时)
|
||||
*/
|
||||
entityEnter(e: ecs.Entity): void {
|
||||
const skillsData = e.get(HeroSkillsComp);
|
||||
const heroModel = e.get(HeroAttrsComp);
|
||||
const request = e.get(CastSkillRequestComp);
|
||||
const heroView = e.get(HeroViewComp);
|
||||
|
||||
// 1. 验证数据完整性
|
||||
if (!skillsData || !heroModel || !request || !heroView) {
|
||||
console.warn("[SkillCastSystem] 数据不完整,取消施法");
|
||||
e.remove(CastSkillRequestComp);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 获取技能数据
|
||||
const skill = skillsData.getSkill(request.skillIndex);
|
||||
if (!skill) {
|
||||
console.warn(`[SkillCastSystem] 技能索引无效: ${request.skillIndex}`);
|
||||
e.remove(CastSkillRequestComp);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 检查施法条件
|
||||
if (!this.checkCastConditions(skillsData, heroModel, request.skillIndex)) {
|
||||
e.remove(CastSkillRequestComp);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 执行施法
|
||||
this.executeCast(e, skill, request.targetPositions, heroView);
|
||||
|
||||
// 5. 扣除资源和重置CD
|
||||
heroModel.mp -= skill.cost;
|
||||
skillsData.resetCD(request.skillIndex);
|
||||
|
||||
// 6. 移除请求标记
|
||||
e.remove(CastSkillRequestComp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查施法条件
|
||||
*/
|
||||
private checkCastConditions(skillsData: HeroSkillsComp, heroModel: HeroAttrsComp, skillIndex: number): boolean {
|
||||
// 检查角色状态
|
||||
if (heroModel.is_dead) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查控制状态(眩晕、冰冻)
|
||||
if (heroModel.isStun() || heroModel.isFrost()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查CD和MP
|
||||
if (!skillsData.canCast(skillIndex, heroModel.mp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行施法
|
||||
*/
|
||||
private executeCast(casterEntity: ecs.Entity, skill: any, targetPositions: Vec3[], heroView: HeroViewComp) {
|
||||
const config = SkillSet[skill.uuid];
|
||||
if (!config) {
|
||||
console.error("[SkillCastSystem] 技能配置不存在:", skill.uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 播放施法动画
|
||||
heroView.playSkillEffect(skill.uuid);
|
||||
|
||||
// 2. 延迟创建技能实体(等待动画)
|
||||
const delay = config.with ?? 0.3; // 施法前摇时间
|
||||
heroView.scheduleOnce(() => {
|
||||
this.createSkillEntity(skill.uuid, heroView, targetPositions);
|
||||
}, delay);
|
||||
|
||||
const heroModel = casterEntity.get(HeroAttrsComp);
|
||||
console.log(`[SkillCastSystem] ${heroModel?.hero_name ?? '未知'} 施放技能: ${config.name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建技能实体
|
||||
*/
|
||||
private createSkillEntity(skillId: number, caster: HeroViewComp, targetPositions: Vec3[]) {
|
||||
// 检查节点有效性
|
||||
if (!caster.node || !caster.node.isValid) {
|
||||
console.warn("[SkillCastSystem] 施法者节点无效");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取场景节点
|
||||
const parent = caster.node.parent;
|
||||
if (!parent) {
|
||||
console.warn("[SkillCastSystem] 场景节点无效");
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ 使用现有的 SkillEnt 创建技能
|
||||
const skillEnt = ecs.getEntity<SkillEnt>(SkillEnt);
|
||||
skillEnt.load(
|
||||
caster.node.position, // 起始位置
|
||||
parent, // 父节点
|
||||
skillId, // 技能ID
|
||||
targetPositions, // 目标位置数组
|
||||
caster, // 施法者
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user