feat(技能系统): 添加最大技能自动施放开关并重构施法逻辑

- 在HeroSkillsComp中添加max_auto字段控制最大技能自动施放
- 重构SACastSystem的施法逻辑,增加返回值判断
- 新增manualCast和manualCastMax方法支持手动施法
- 删除废弃的SCastSystem文件
This commit is contained in:
2025-11-19 10:34:37 +08:00
parent e42bdbb671
commit 9f809b1ffa
3 changed files with 39 additions and 154 deletions

View File

@@ -38,6 +38,7 @@ export class HeroSkillsComp extends ecs.Comp {
// ==================== 技能槽位列表 ====================
/** 技能槽位数组最多4个技能 */
skills: Record<number, SkillSlot> = {};
max_auto: boolean = true;
// ==================== 辅助方法 ====================
@@ -270,4 +271,7 @@ export class HeroSkillsComp extends ecs.Comp {
reset() {
this.skills = {};
}
setMaxAuto(on: boolean) {
this.max_auto = on;
}
}

View File

@@ -52,6 +52,7 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
for (const s_uuid of readySkills) {
const skill = skills.getSkill(s_uuid);
if (!skill) continue;
if (skill.hset === HSSet.max && !skills.max_auto) continue;
const config = SkillSet[skill.s_uuid];
if (!config || config.SType !== SType.damage) continue;
@@ -66,20 +67,44 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
break;
}
}
private startCast(e: ecs.Entity,skill:SkillSlot,hset:HSSet): void {
if (!skill||!e) return
private startCast(e: ecs.Entity,skill:SkillSlot,hset:HSSet): boolean {
if (!skill||!e) return false
const skills = e.get(HeroSkillsComp);
const heroAttrs = e.get(HeroAttrsComp);
const heroView = e.get(HeroViewComp);
// 3. 检查施法条件
if (!this.checkCastConditions(skills, heroAttrs, skill.s_uuid)) return
if (!this.checkCastConditions(skills, heroAttrs, skill.s_uuid)) return false
// 4. 执行施法
this.executeCast(e, skill.s_uuid, heroView,hset);
const ok = this.executeCast(e, skill.s_uuid, heroView,hset);
// 5. 扣除资源和重置CD
heroAttrs.mp -= skill.cost;
skills.resetCD(skill.s_uuid);
if (ok) {
heroAttrs.mp -= skill.cost;
skills.resetCD(skill.s_uuid);
}
return ok;
}
public manualCast(e: ecs.Entity, s_uuid: number): boolean {
if (!e) return false
const skills = e.get(HeroSkillsComp)
const heroAttrs = e.get(HeroAttrsComp)
const heroView = e.get(HeroViewComp)
if (!skills || !heroAttrs || !heroView) return false
const slot = skills.getSkill(s_uuid)
if (!slot) return false
return this.startCast(e, slot, slot.hset)
}
public manualCastMax(e: ecs.Entity): boolean {
const skills = e.get(HeroSkillsComp)
if (!skills) return false
for (const key in skills.skills) {
const s_uuid = Number(key)
const slot = skills.getSkill(s_uuid)
if (slot && slot.hset === HSSet.max) {
return this.manualCast(e, s_uuid)
}
}
return false
}
/**
* 检查施法条件
@@ -106,11 +131,11 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
/**
* 执行施法
*/
private executeCast(casterEntity: ecs.Entity, s_uuid: number, heroView: HeroViewComp,hset:HSSet) {
private executeCast(casterEntity: ecs.Entity, s_uuid: number, heroView: HeroViewComp,hset:HSSet): boolean {
const config = SkillSet[s_uuid];
if (!config) {
console.error("[SACastSystem] 技能配置不存在:", s_uuid);
return;
return false;
}
// 1. 播放施法动画
heroView.playSkillEffect(s_uuid);
@@ -144,6 +169,7 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
const heroAttrs = casterEntity.get(HeroAttrsComp);
// console.log(`[SACastSystem] ${heroAttrs?.hero_name ?? '未知'} 施放技能: ${config.name}`);
return true;
}

View File

@@ -1,145 +0,0 @@
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 { HeroSkillsComp } from "./HeroSkills";
import { Skill } from "../skill/Skill";
import { CSRequestComp } from "../skill/STagComps";
import { smc } from "../common/SingletonModuleComp";
/**
* ==================== 技能施法系统 手动施法====================
*
* 职责:
* 1. 监听 CSRequestComp 标记组件
* 2. 检查施法条件CD、MP、状态
* 3. 扣除资源MP
* 4. 创建技能实体
* 5. 触发施法动画
* 6. 移除请求标记
*
* 设计理念:
* - 使用标记组件驱动,符合 ECS 理念
* - 施法检查与执行分离
* - 自动处理资源消耗和CD重置
*/
// @ecs.register('SCastSystem')
export class SCastSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
/**
* 过滤器:拥有技能数据 + 施法请求的实体
*/
filter(): ecs.IMatcher {
return ecs.allOf(HeroSkillsComp, HeroAttrsComp, CSRequestComp);
}
/**
* 实体进入时触发(即请求施法时)
*/
entityEnter(e: ecs.Entity): void {
if(!smc.mission.play || smc.mission.pause) return;
const skillsComp = e.get(HeroSkillsComp);
const heroAttrs = e.get(HeroAttrsComp);
const request = e.get(CSRequestComp);
const heroView = e.get(HeroViewComp);
// 1. 验证数据完整性
if (!skillsComp || !heroAttrs || !request || !heroView) {
console.warn("[SCastSystem] 数据不完整,取消施法");
e.remove(CSRequestComp);
return;
}
// 2. 获取技能数据
const skill = skillsComp.getSkill(request.s_uuid);
if (!skill) {
console.warn(`[SCastSystem] 技能索引无效: ${request.s_uuid }`);
e.remove(CSRequestComp);
return;
}
// 3. 检查施法条件
if (!this.checkCastConditions(skillsComp, heroAttrs, request.s_uuid)) {
e.remove(CSRequestComp);
return;
}
// 4. 执行施法
this.executeCast(e, skill, request.targets, heroView);
// 5. 扣除资源和重置CD
heroAttrs.mp -= skill.cost;
skillsComp.resetCD(request.s_uuid);
// 6. 移除请求标记
e.remove(CSRequestComp);
}
/**
* 检查施法条件
*/
private checkCastConditions(skillsComp: HeroSkillsComp, heroAttrs: HeroAttrsComp, skillIndex: number): boolean {
// 检查角色状态
if (heroAttrs.is_dead) {
return false;
}
// 检查控制状态(眩晕、冰冻)
if (heroAttrs.isStun() || heroAttrs.isFrost()) {
return false;
}
// 检查CD和MP
if (!skillsComp.canCast(skillIndex, heroAttrs.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("[SCastSystem] 技能配置不存在:", 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 heroAttrs = casterEntity.get(HeroAttrsComp);
console.log(`[SCastSystem] ${heroAttrs?.hero_name ?? '未知'} 施放技能: ${config.name}`);
}
/**
* 创建技能实体
*/
private createSkill(skillId: number, caster: HeroViewComp, targets: Vec3[]) {
// 检查节点有效性
if (!caster.node || !caster.node.isValid) {
console.warn("[SCastSystem] 施法者节点无效");
return;
}
// 获取场景节点
const parent = caster.node.parent;
if (!parent) {
console.warn("[SCastSystem] 场景节点无效");
return;
}
// ✅ 使用现有的 SkillEnt 创建技能
// const skill = ecs.getEntity<Skill>(Skill);
}
}