import { _decorator, resources, JsonAsset } from 'cc'; import { BaseSingleton } from './BaseSingleton'; const { ccclass, property } = _decorator; // 武器配置接口 export interface WeaponConfig { id: string; name: string; type: string; rarity: string; weight: number; stats: { damage: number; fireRate: number; range: number; bulletSpeed: number; penetration: number; accuracy: number; explosionRadius?: number; explosionDamage?: number; burnDuration?: number; burnDamage?: number; returnSpeed?: number; homingStrength?: number; }; bulletConfig: { bulletType: string; bulletPrefab: string; hitEffect: string; trailEffect?: string; ricochetCount?: number; ricochetAngle?: number; explosionDelay?: number; burnEffect?: string; arcHeight?: number; returnDelay?: number; homingDelay?: number; }; attackPattern: { type: string; projectileCount: number; spreadAngle: number; burstCount: number; burstDelay: number; }; visualConfig: { weaponSprites: { [size: string]: string; }; muzzleFlash: string; fireSound: string; }; } // 球控制器配置接口 export interface BallControllerConfig { baseSpeed: number; maxReflectionRandomness: number; antiTrapTimeWindow: number; antiTrapHitThreshold: number; deflectionAttemptThreshold: number; antiTrapDeflectionMultiplier: number; FIRE_COOLDOWN: number; ballRadius: number; gravityScale: number; linearDamping: number; angularDamping: number; colliderGroup: number; colliderTag: number; friction: number; restitution: number; safeDistance: number; edgeOffset: number; sensor: boolean; maxAttempts: number; } // 敌人配置接口 export interface EnemyConfig { id: string; name: string; type: string; rarity: string; weight: number; health: number; speed: number; attack: number; range: number; attackSpeed: number; defense: number; goldReward: number; explosionDamage?: number; explosionRadius?: number; movement: { type: string; pattern: string; speedVariation: number; swayAmplitude?: number; swayFrequency?: number; }; combat: { attackType: string; attackDelay: number; attackCooldown: number; weaponType?: string; projectileType?: string; projectileSpeed?: number; canBlock: boolean; blockChance: number; }; visualConfig: { spritePrefab: string; animations: { [state: string]: string; }; scale: number; flipX: boolean; weapon?: string; armor?: string; prop?: string; }; audioConfig: { [sound: string]: string; }; specialAbilities: string[]; stealthConfig?: { stealthDuration: number; stealthCooldown: number; revealOnAttack: boolean; visibilityAlpha: number; }; armorConfig?: { armorHealth: number; armorReduction: number; breakThreshold: number; }; explosionConfig?: { explosionDelay: number; explosionEffect: string; damageRadius: number; knockbackForce: number; }; bossConfig?: { phases: number; phaseHealthThreshold: number; enrageBonus?: { speed: number; damage: number; attackSpeed: number; }; summonAbility?: { minionType: string; summonCount: number; summonCooldown: number; }; laserAbility?: { damage: number; range: number; chargeTime: number; cooldown: number; }; }; projectileConfig?: { bulletPrefab: string; hitEffect: string; trailEffect?: string; }; } @ccclass('ConfigManager') export class ConfigManager extends BaseSingleton { // 仅用于类型声明,实例由 BaseSingleton 在运行时动态维护 public static _instance: ConfigManager; private weaponsConfig: any = null; private enemiesConfig: any = null; private configLoaded: boolean = false; // 武器权重缓存 private weaponWeightedList: WeaponConfig[] = []; // 敌人权重缓存 private enemyWeightedList: EnemyConfig[] = []; /** * BaseSingleton 首次实例化回调 */ protected init() { console.log('[ConfigManager] 开始初始化配置管理器'); this.loadConfigs(); } // 加载所有配置文件 private async loadConfigs() { console.log('[ConfigManager] 开始加载配置文件'); this.configLoaded = false; try { // 确保resources bundle已经准备好 await this.ensureResourcesBundle(); // 加载武器配置 console.log('[ConfigManager] 开始加载武器配置'); await this.loadWeaponsConfig(); console.log('[ConfigManager] 武器配置加载完成'); // 加载敌人配置 console.log('[ConfigManager] 开始加载敌人配置'); await this.loadEnemiesConfig(); console.log('[ConfigManager] 敌人配置加载完成'); // 注意:球控制器配置现在通过BallController组件的装饰器直接加载 console.log('[ConfigManager] 球控制器配置通过装饰器加载,跳过ConfigManager加载'); this.configLoaded = true; console.log('[ConfigManager] ✅ 所有配置文件加载成功,配置管理器初始化完成'); } catch (error) { console.error('[ConfigManager] ❌ 配置文件加载失败:', error); this.configLoaded = false; // 延迟重试加载 console.log('[ConfigManager] 将在3秒后重试加载配置'); setTimeout(() => { console.log('[ConfigManager] 开始重试加载配置'); this.loadConfigs(); }, 3000); } } // 确保resources bundle已经准备好 private ensureResourcesBundle(): Promise { return new Promise((resolve) => { console.log('[ConfigManager] 检查resources bundle状态...'); // 简单延迟确保Cocos Creator资源系统已经初始化 setTimeout(() => { console.log('[ConfigManager] resources bundle初始化等待完成'); resolve(); }, 1000); }); } // 加载武器配置 private loadWeaponsConfig(): Promise { return new Promise((resolve, reject) => { console.log('加载武器配置...'); resources.load('data/weapons', JsonAsset, (err, asset) => { if (err) { console.error('武器配置文件加载失败:', err); reject(err); return; } if (!asset || !asset.json) { console.error('武器配置文件内容为空'); reject(new Error('武器配置文件内容为空')); return; } this.weaponsConfig = asset.json as any; console.log('✅ 武器配置加载成功'); this.buildWeaponWeightedList(); resolve(); }); }); } // 加载敌人配置 private loadEnemiesConfig(): Promise { return new Promise((resolve, reject) => { console.log('加载敌人配置...'); resources.load('data/enemies', JsonAsset, (err, asset) => { if (err) { console.error('敌人配置文件加载失败:', err); reject(err); return; } if (!asset || !asset.json) { console.error('敌人配置文件内容为空'); reject(new Error('敌人配置文件内容为空')); return; } this.enemiesConfig = asset.json as any; console.log('✅ 敌人配置加载成功'); this.buildEnemyWeightedList(); resolve(); }); }); } // 加载球控制器配置 // 球控制器配置现在通过BallController组件的装饰器直接加载,不再需要在ConfigManager中处理 // 构建武器权重列表 private buildWeaponWeightedList() { if (!this.weaponsConfig) return; this.weaponWeightedList = []; this.weaponsConfig.weapons.forEach(weapon => { // 根据权重添加多次到列表中 for (let i = 0; i < weapon.weight; i++) { this.weaponWeightedList.push(weapon); } }); console.log('武器权重列表构建完成,总权重:', this.weaponWeightedList.length); } // 构建敌人权重列表 private buildEnemyWeightedList() { if (!this.enemiesConfig) return; this.enemyWeightedList = []; this.enemiesConfig.enemies.forEach(enemy => { // 根据权重添加多次到列表中 for (let i = 0; i < enemy.weight; i++) { this.enemyWeightedList.push(enemy); } }); console.log('敌人权重列表构建完成,总权重:', this.enemyWeightedList.length); } // 随机获取武器配置 public getRandomWeapon(rarity?: string): WeaponConfig | null { if (!this.weaponsConfig || this.weaponWeightedList.length === 0) { console.warn('武器配置未加载或为空'); return null; } if (rarity) { // 按稀有度筛选 const filteredWeapons = this.weaponsConfig.weapons.filter(weapon => weapon.rarity === rarity); if (filteredWeapons.length === 0) { console.warn(`没有找到稀有度为 ${rarity} 的武器`); return null; } const randomIndex = Math.floor(Math.random() * filteredWeapons.length); return filteredWeapons[randomIndex]; } // 使用稀有度权重系统进行随机选择 const rarityWeights = this.weaponsConfig.rarityWeights; if (!rarityWeights) { console.warn('稀有度权重配置未找到,使用武器权重列表'); const randomIndex = Math.floor(Math.random() * this.weaponWeightedList.length); return this.weaponWeightedList[randomIndex]; } // 计算总权重 // 计算总权重(兼容ES5) const totalWeight = Object.keys(rarityWeights).reduce((sum: number, key: string) => sum + (rarityWeights[key] as number), 0); const randomValue = Math.random() * totalWeight; // 根据权重选择稀有度 let currentWeight = 0; let selectedRarity = 'common'; // 兼容ES5的写法遍历对象 for (let rarity in rarityWeights) { if (rarityWeights.hasOwnProperty(rarity)) { const weight = rarityWeights[rarity]; currentWeight += weight as number; if (randomValue <= currentWeight) { selectedRarity = rarity; break; } } // 从选中的稀有度中随机选择武器 const weaponsOfRarity = this.weaponsConfig.weapons.filter(weapon => weapon.rarity === selectedRarity); if (weaponsOfRarity.length === 0) { console.warn(`稀有度 ${selectedRarity} 没有可用武器,使用武器权重列表`); const randomIndex = Math.floor(Math.random() * this.weaponWeightedList.length); return this.weaponWeightedList[randomIndex]; } const randomIndex = Math.floor(Math.random() * weaponsOfRarity.length); const selectedWeapon = weaponsOfRarity[randomIndex]; console.log(`随机选择武器: ${selectedWeapon.name} (${selectedRarity})`); return selectedWeapon; } } // 随机获取敌人配置 public getRandomEnemy(rarity?: string): EnemyConfig | null { if (!this.enemiesConfig || this.enemyWeightedList.length === 0) { console.warn('敌人配置未加载或为空'); return null; } if (rarity) { // 按稀有度筛选 const filteredEnemies = this.enemiesConfig.enemies.filter(enemy => enemy.rarity === rarity); if (filteredEnemies.length === 0) { console.warn(`没有找到稀有度为 ${rarity} 的敌人`); return null; } const randomIndex = Math.floor(Math.random() * filteredEnemies.length); return filteredEnemies[randomIndex]; } // 从权重列表中随机选择 const randomIndex = Math.floor(Math.random() * this.enemyWeightedList.length); return this.enemyWeightedList[randomIndex]; } // 根据ID获取武器配置 public getWeaponById(id: string): WeaponConfig | null { if (!this.weaponsConfig) return null; return this.weaponsConfig.weapons.find(weapon => weapon.id === id) || null; } // 根据ID获取敌人配置 public getEnemyById(id: string): EnemyConfig | null { if (!this.enemiesConfig) return null; return this.enemiesConfig.enemies.find(enemy => enemy.id === id) || null; } /** * 获取敌人名称到ID的映射 */ public getNameToIdMapping(): { [key: string]: string } | null { if (!this.enemiesConfig) return null; return this.enemiesConfig.nameToIdMapping || null; } // 获取所有武器配置 public getAllWeapons(): WeaponConfig[] { return this.weaponsConfig?.weapons || []; } // 获取所有敌人配置 public getAllEnemies(): EnemyConfig[] { return this.enemiesConfig?.enemies || []; } // 根据稀有度获取武器列表 public getWeaponsByRarity(rarity: string): WeaponConfig[] { if (!this.weaponsConfig) return []; return this.weaponsConfig.weapons.filter(weapon => weapon.rarity === rarity); } // 根据稀有度获取敌人列表 public getEnemiesByRarity(rarity: string): EnemyConfig[] { if (!this.enemiesConfig) return []; return this.enemiesConfig.enemies.filter(enemy => enemy.rarity === rarity); } // 获取方块尺寸列表(已更新为形状ID) public getBlockSizes(): string[] { if (!this.weaponsConfig || !this.weaponsConfig.blockSizes) { return ['I', 'H-I', 'L', 'S', 'D-T']; } // 从blockSizes配置中提取形状ID return this.weaponsConfig.blockSizes.map((shape: any) => shape.id); } // 获取方块形状配置列表 public getBlockShapes(): any[] { if (!this.weaponsConfig || !this.weaponsConfig.blockSizes) { console.warn('武器配置或方块形状配置未加载'); return []; } return this.weaponsConfig.blockSizes; } // 获取波次进展配置 public getWaveProgression(): any { return this.enemiesConfig?.waveProgression || {}; } // 根据波次获取合适的敌人 public getEnemyForWave(waveNumber: number): EnemyConfig | null { if (!this.enemiesConfig) return null; const progression = this.enemiesConfig.waveProgression; let enemyPool: string[] = []; if (waveNumber <= 5) { enemyPool = progression.earlyWaves || []; } else if (waveNumber <= 15) { enemyPool = [...(progression.earlyWaves || []), ...(progression.midWaves || [])]; } else if (waveNumber <= 25) { enemyPool = [...(progression.midWaves || []), ...(progression.lateWaves || [])]; } else { enemyPool = [...(progression.lateWaves || []), ...(progression.bossWaves || [])]; } if (enemyPool.length === 0) { return this.getRandomEnemy(); } const randomId = enemyPool[Math.floor(Math.random() * enemyPool.length)]; return this.getEnemyById(randomId); } // 检查配置是否已加载 public isConfigLoaded(): boolean { return this.configLoaded; } // 获取球控制器配置 // getBallControllerConfig方法已移除,球控制器配置现在通过装饰器直接在BallController中加载 }