Files
heros/assets/script/game/hero/SCastSystem.ts
panw b38e63e200 refactor(skill): 重构技能组件目录结构并重命名施法请求组件
将技能相关组件从hero目录移动到skill目录
将CastSkillRequestComp重命名为CSRequestComp
更新相关引用和文档说明
2025-10-31 09:22:50 +08:00

144 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { Vec3, v3 } from "cc";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { SkillSet, SType } from "../common/config/SkillSet";
import { SkillEnt } from "../skill/SkillEnt";
import { HeroSkillsComp } from "./HeroSkills";
import { Skill } from "../skill/Skill";
import { CSRequestComp } from "../skill/STagComps";
/**
* ==================== 技能施法系统 手动施法====================
*
* 职责:
* 1. 监听 CSRequestComp 标记组件
* 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, CSRequestComp);
}
/**
* 实体进入时触发(即请求施法时)
*/
entityEnter(e: ecs.Entity): void {
const skills = e.get(HeroSkillsComp);
const heroModel = e.get(HeroAttrsComp);
const request = e.get(CSRequestComp);
const heroView = e.get(HeroViewComp);
// 1. 验证数据完整性
if (!skills || !heroModel || !request || !heroView) {
console.warn("[SkillCastSystem] 数据不完整,取消施法");
e.remove(CSRequestComp);
return;
}
// 2. 获取技能数据
const skill = skills.getSkill(request.skillIndex);
if (!skill) {
console.warn(`[SkillCastSystem] 技能索引无效: ${request.skillIndex}`);
e.remove(CSRequestComp);
return;
}
// 3. 检查施法条件
if (!this.checkCastConditions(skills, heroModel, request.skillIndex)) {
e.remove(CSRequestComp);
return;
}
// 4. 执行施法
this.executeCast(e, skill, request.targets, heroView);
// 5. 扣除资源和重置CD
heroModel.mp -= skill.cost;
skills.resetCD(request.skillIndex);
// 6. 移除请求标记
e.remove(CSRequestComp);
}
/**
* 检查施法条件
*/
private checkCastConditions(skills: HeroSkillsComp, heroModel: HeroAttrsComp, skillIndex: number): boolean {
// 检查角色状态
if (heroModel.is_dead) {
return false;
}
// 检查控制状态(眩晕、冰冻)
if (heroModel.isStun() || heroModel.isFrost()) {
return false;
}
// 检查CD和MP
if (!skills.canCast(skillIndex, heroModel.mp)) {
return false;
}
return true;
}
/**
* 执行施法
*/
private executeCast(casterEntity: ecs.Entity, skill: any, targets: 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.createSkill(skill.uuid, heroView, targets);
}, delay);
const heroModel = casterEntity.get(HeroAttrsComp);
console.log(`[SkillCastSystem] ${heroModel?.hero_name ?? '未知'} 施放技能: ${config.name}`);
}
/**
* 创建技能实体
*/
private createSkill(skillId: number, caster: HeroViewComp, targets: Vec3[]) {
// 检查节点有效性
if (!caster.node || !caster.node.isValid) {
console.warn("[SkillCastSystem] 施法者节点无效");
return;
}
// 获取场景节点
const parent = caster.node.parent;
if (!parent) {
console.warn("[SkillCastSystem] 场景节点无效");
return;
}
// ✅ 使用现有的 SkillEnt 创建技能
// const skill = ecs.getEntity<Skill>(Skill);
}
}