import { _decorator, Component, sys } from 'cc'; import { SkillConfigManager } from './SkillConfigManager'; const { ccclass, property } = _decorator; /** * 技能类型枚举 */ export enum PersistentSkillType { BALL_SPEED = 'ball_speed', DAMAGE = 'damage', CRIT_DAMAGE = 'crit_damage' } /** * 技能点亮数据接口 */ export interface SkillUnlockData { skillType: string; // 'damage', 'ball_speed', 'crit_damage' effectPercent: number; // 该节点的效果百分比 group: number; // 技能组别 unlocked: boolean; // 是否已点亮 } /** * 持久化技能管理器 - 单例模式 * 负责接收技能点亮数据,计算累积效果,并保存到本地存储 */ @ccclass('PersistentSkillManager') export class PersistentSkillManager extends Component { private static _instance: PersistentSkillManager | null = null; private _unlockedSkills: Map = new Map(); private _saveKey = 'persistent_skills_unlocked_data'; private _skillConfigManager: SkillConfigManager | null = null; public static getInstance(): PersistentSkillManager | null { return PersistentSkillManager._instance; } onLoad() { if (PersistentSkillManager._instance === null) { PersistentSkillManager._instance = this; this._skillConfigManager = SkillConfigManager.getInstance(); this.initSkillData(); this.loadSkillData(); } else { this.destroy(); return; } } onDestroy() { if (PersistentSkillManager._instance === this) { PersistentSkillManager._instance = null; } } /** * 初始化技能数据结构 */ private initSkillData() { this._unlockedSkills.set('damage', []); this._unlockedSkills.set('ball_speed', []); this._unlockedSkills.set('crit_damage', []); } /** * 报告技能点亮 * @param skillType 技能类型 * @param effectPercent 效果百分比 * @param group 技能组别 */ public reportSkillUnlocked(skillType: string, effectPercent: number, group: number) { const skillArray = this._unlockedSkills.get(skillType); if (!skillArray) { console.error(`未知的技能类型: ${skillType}`); return; } // 检查是否已经存在相同的技能节点 const existingSkill = skillArray.find(skill => skill.group === group); if (existingSkill) { console.log(`技能节点已存在: ${skillType} Group ${group}`); return; } // 添加新的技能点亮数据 const skillData: SkillUnlockData = { skillType, effectPercent, group, unlocked: true }; skillArray.push(skillData); // 按组别排序 skillArray.sort((a, b) => a.group - b.group); // 保存数据 this.saveSkillData(); const displayName = this.getSkillTypeDisplayName(skillType); console.log(`技能点亮成功: ${displayName} +${effectPercent}% (Group ${group})`); console.log(`当前${displayName}总加成: ${this.calculateTotalEffect(skillType)}%`); } /** * 计算指定技能类型的总效果(按最新点亮的节点值,不再对历史节点累加) * @param skillType 技能类型 * @returns 总效果百分比 */ private calculateTotalEffect(skillType: string): number { const skillArray = this._unlockedSkills.get(skillType); if (!skillArray || skillArray.length === 0) { return 0; } // 返回已点亮节点中最大的效果值(因顺序解锁,最大即最新) let latestEffect = 0; for (let i = 0; i < skillArray.length; i++) { const skill = skillArray[i]; if (skill.unlocked) { latestEffect = Math.max(latestEffect, skill.effectPercent); } } return latestEffect; } /** * 获取技能加成信息 * @returns 技能加成信息 */ public getSkillBonuses() { return { ballSpeedBonus: this.calculateTotalEffect('ball_speed'), damageBonus: this.calculateTotalEffect('damage'), critDamageBonus: this.calculateTotalEffect('crit_damage') }; } /** * 应用技能加成到数值 * @param baseBallSpeed 基础球速 * @param baseDamage 基础伤害 * @param baseCritDamage 基础暴击伤害 * @returns 加成后的数值 */ public applySkillBonuses(baseBallSpeed: number, baseDamage: number, baseCritDamage: number) { const bonuses = this.getSkillBonuses(); return { ballSpeed: baseBallSpeed * (1 + bonuses.ballSpeedBonus / 100), damage: baseDamage * (1 + bonuses.damageBonus / 100), critDamage: baseCritDamage * (1 + bonuses.critDamageBonus / 100) }; } /** * 应用球速加成 * @param baseBallSpeed 基础球速 * @returns 加成后的球速 */ public applyBallSpeedBonus(baseBallSpeed: number): number { const bonus = this.calculateTotalEffect('ball_speed'); return baseBallSpeed * (1 + bonus / 100); } /** * 应用伤害加成 * @param baseDamage 基础伤害 * @returns 加成后的伤害 */ public applyDamageBonus(baseDamage: number): number { const bonus = this.calculateTotalEffect('damage'); return baseDamage * (1 + bonus / 100); } /** * 应用暴击伤害加成 * @param baseCritDamage 基础暴击伤害 * @returns 加成后的暴击伤害 */ public applyCritDamageBonus(baseCritDamage: number): number { const bonus = this.calculateTotalEffect('crit_damage'); return baseCritDamage * (1 + bonus / 100); } /** * 获取指定技能类型的所有点亮数据 * @param skillType 技能类型 * @returns 技能点亮数据数组 */ public getUnlockedSkills(skillType: string): SkillUnlockData[] { return this._unlockedSkills.get(skillType) || []; } /** * 获取所有技能的点亮数据 * @returns 所有技能数据 */ public getAllUnlockedSkills(): Map { return this._unlockedSkills; } /** * 保存技能数据到本地存储 */ private saveSkillData() { const saveData = { damage: this._unlockedSkills.get('damage') || [], ball_speed: this._unlockedSkills.get('ball_speed') || [], crit_damage: this._unlockedSkills.get('crit_damage') || [] }; const jsonData = JSON.stringify(saveData); sys.localStorage.setItem(this._saveKey, jsonData); console.log('技能数据已保存到本地存储'); } /** * 从本地存储加载技能数据 */ private loadSkillData() { const saveData = sys.localStorage.getItem(this._saveKey); if (saveData) { try { const parsedData = JSON.parse(saveData); this._unlockedSkills.set('damage', parsedData.damage || []); this._unlockedSkills.set('ball_speed', parsedData.ball_speed || []); this._unlockedSkills.set('crit_damage', parsedData.crit_damage || []); console.log('技能数据加载成功'); console.log('当前技能加成:', this.getSkillBonuses()); } catch (error) { console.error('加载技能数据失败:', error); this.initSkillData(); } } else { console.log('未找到保存的技能数据,使用默认数据'); } } /** * 重置所有技能数据(调试用) */ public resetAllSkills() { this.initSkillData(); this.saveSkillData(); console.log('所有技能数据已重置'); } /** * 获取技能统计信息 */ public getSkillStats() { const stats = { damage: { unlockedCount: this.getUnlockedSkills('damage').length, totalEffect: this.calculateTotalEffect('damage') }, ballSpeed: { unlockedCount: this.getUnlockedSkills('ball_speed').length, totalEffect: this.calculateTotalEffect('ball_speed') }, critDamage: { unlockedCount: this.getUnlockedSkills('crit_damage').length, totalEffect: this.calculateTotalEffect('crit_damage') } }; return stats; } /** * 检查技能是否已点亮 * @param skillType 技能类型 * @param group 技能组别 * @returns 是否已点亮 */ /** * 检查技能是否已点亮 * @param skillType 技能类型 * @param group 技能组别 * @returns 是否已点亮 */ public checkSkillUnlocked(skillType: string, group: number): boolean { const skillArray = this._unlockedSkills.get(skillType); if (!skillArray) { return false; } return skillArray.some(skill => skill.group === group && skill.unlocked); } /** * 检查技能是否可以解锁 * 该方法仅供参考,实际解锁逻辑由 SkillNodeGenerator 负责 * @param skillType 技能类型 * @param group 技能组别 * @returns 是否可以解锁 */ public canUnlockSkill(skillType: string, group: number): boolean { // 该方法不再负责解锁验证,始终返回 true // 实际解锁逻辑由 SkillNodeGenerator 负责 return true; } /** * 接收技能解锁数据 * @param skillType 技能类型 * @param group 技能组别 * @param effectPercent 效果百分比 * @returns 解锁结果 {success: boolean, message: string} */ public unlockSkill(skillType: string, group: number, effectPercent: number): {success: boolean, message: string} { // 检查技能类型是否有效 const skillArray = this._unlockedSkills.get(skillType); if (!skillArray) { return {success: false, message: `未知的技能类型: ${skillType}`}; } // 检查是否已经解锁(避免重复解锁) if (this.isSkillUnlocked(skillType, group)) { return {success: false, message: `技能已解锁: ${this.getSkillTypeDisplayName(skillType)} Group ${group}`}; } // 直接接收解锁数据,不进行验证 // 解锁验证逻辑由 SkillNodeGenerator 负责 this.reportSkillUnlocked(skillType, effectPercent, group); return {success: true, message: `技能解锁成功: ${this.getSkillTypeDisplayName(skillType)} +${effectPercent}% (Group ${group})`}; } /** * 获取技能解锁所需的钻石数量 * @param group 技能组别 * @returns 所需钻石数量 */ public getSkillCost(group: number): number { if (this._skillConfigManager) { return this._skillConfigManager.getSkillCost(group); } // 如果配置管理器未初始化,使用默认公式 return 10 + (group - 1) * 10; } /** * 获取技能效果百分比 * @param skillType 技能类型 * @returns 效果百分比 */ public getSkillEffectPercent(skillType: PersistentSkillType): number { return this.calculateTotalEffect(skillType); } /** * 获取技能等级(点亮的节点数量) * @param skillType 技能类型 * @returns 技能等级 */ public getSkillLevel(skillType: PersistentSkillType): number { const skillArray = this._unlockedSkills.get(skillType); if (!skillArray) { return 0; } return skillArray.filter(skill => skill.unlocked).length; } // 已删除重复的 getSkillTypeDisplayName 方法,使用下方的中文版本 /** * 检查技能是否已解锁 */ public isSkillUnlocked(skillType: string, group: number): boolean { const skillArray = this._unlockedSkills.get(skillType); if (!skillArray) { return false; } return skillArray.some(skill => skill.group === group && skill.unlocked); } /** * 获取技能类型的显示名称 */ private getSkillTypeDisplayName(skillType: string): string { if (this._skillConfigManager) { // 根据技能类型找到对应的索引 const skillConfig = this._skillConfigManager.getSkillConfig(); if (skillConfig) { const skillTypeConfig = skillConfig.skillTypes.find(config => config.type === skillType); if (skillTypeConfig) { return skillTypeConfig.displayName; } } } // 如果配置管理器未初始化或找不到配置,使用默认名称 switch (skillType) { case 'damage': return '伤害'; case 'ball_speed': return '球速'; case 'crit_damage': return '暴击伤害'; default: return skillType; } } }