Files
heros/assets/script/game/hero/HeroSkills.ts
panw 2b3b80b308 refactor(技能系统): 重构技能系统以使用s_uuid作为主键并优化技能施放逻辑
- 将HeroSkillsComp中的技能数组改为以s_uuid为键的对象存储
- 修改CSRequestComp使用s_uuid替代skillIndex
- 优化SkillCastSystem和SACastSystem的施放逻辑
- 为SMoveDataComp添加rePos方法处理技能位置计算
- 移除未使用的SDataComSystem代码
2025-10-31 10:47:05 +08:00

167 lines
4.3 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 { SkillSet } from "../common/config/SkillSet";
/**
* ==================== 技能槽位数据 ====================
* 单个技能的运行时数据
*/
export interface SkillSlot {
s_uuid: number; // 技能配置ID
cd: number; // 当前CD时间递减
cd_max: number; // 最大CD时间
cost: number; // MP消耗
level: number; // 技能等级(预留)
}
/**
* ==================== 英雄技能数据组件 ====================
*
* 职责:
* 1. 存储角色拥有的技能列表
* 2. 管理技能CD状态
* 3. 提供技能查询接口
*
* 设计理念:
* - 只存数据,不含施法逻辑
* - CD 更新由 HSkillSystem 负责
* - 施法判定由 HSkillSystem 负责
*/
@ecs.register('HeroSkills')
export class HeroSkillsComp extends ecs.Comp {
// ==================== 技能槽位列表 ====================
/** 技能槽位数组最多4个技能 */
skills: Record<number, SkillSlot> = {};
// ==================== 辅助方法 ====================
/**
* 初始化技能列表
* @param sUuids 技能配置ID数组
*/
initSkills(sUuids: number[]) {
this.skills = [];
for (const s_uuid of sUuids) {
const config = SkillSet[s_uuid];
if (!config) {
console.warn(`[HeroSkills] 技能配置不存在: ${s_uuid}`);
continue;
}
this.skills[s_uuid]={
s_uuid: config.uuid,
cd: 0,
cd_max: config.cd,
cost: config.cost,
level: 1,
}
}
}
/**
* 添加单个技能
*/
addSkill(s_uuid: number) {
const config = SkillSet[s_uuid];
if (!config) {
console.warn(`[HeroSkills] 技能配置不存在: ${s_uuid}`);
return;
}
this.skills[s_uuid] = {
s_uuid: config.uuid,
cd: 0,
cd_max: config.cd,
cost: config.cost,
level: 1
};
}
/**
* 获取指定s_uuid的技能
*/
getSkill(s_uuid: number): SkillSlot | null {
return this.skills[s_uuid] ?? null;
}
/**
* 检查技能是否可施放(通过索引)
* @param index 技能索引
* @param currentMp 当前MP值
*/
canCast(s_uuid: number, currentMp: number): boolean {
const skill = this.getSkill(s_uuid);
if (!skill) return false;
// 检查CD和MP
return skill.cd <= 0 && currentMp >= skill.cost;
}
/**
* 检查技能是否可施放通过s_uuid
* @param s_uuid 技能配置ID
* @param currentMp 当前MP值
*/
canCastByUuid(s_uuid: number, currentMp: number): boolean {
const skill = this.getSkill(s_uuid);
if (!skill) return false;
// 检查CD和MP
return skill.cd <= 0 && currentMp >= skill.cost;
}
/**
* 重置技能CD开始冷却通过索引
* @param index 技能索引
*/
resetCD(s_uuid: number) {
const skill = this.getSkill(s_uuid);
if (skill) {
skill.cd = skill.cd_max;
}
}
/**
* 重置技能CD开始冷却通过s_uuid
* @param s_uuid 技能配置ID
*/
resetCDByUuid(s_uuid: number) {
const skill = this.getSkill(s_uuid);
if (skill) {
skill.cd = skill.cd_max;
}
}
/**
* 更新所有技能CD每帧调用
* @param dt 时间增量
*/
updateCDs(dt: number) {
for (const s_uuid in this.skills) {
const skill = this.skills[Number(s_uuid)];
if (skill.cd > 0) {
skill.cd -= dt;
if (skill.cd < 0) {
skill.cd = 0;
}
}
}
}
/**
* 获取所有可施放的技能索引
*/
getReadySkills(currentMp: number): number[] {
const ready: number[] = [];
for (const s_uuid in this.skills) {
if (this.canCastByUuid(Number(s_uuid), currentMp)) {
ready.push(Number(s_uuid));
}
}
return ready;
}
reset() {
this.skills = {};
}
}