ConfigManager.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. import { _decorator, Component, resources, JsonAsset } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. // 武器配置接口
  4. export interface WeaponConfig {
  5. id: string;
  6. name: string;
  7. type: string;
  8. rarity: string;
  9. weight: number;
  10. stats: {
  11. damage: number;
  12. fireRate: number;
  13. range: number;
  14. bulletSpeed: number;
  15. penetration: number;
  16. accuracy: number;
  17. explosionRadius?: number;
  18. explosionDamage?: number;
  19. burnDuration?: number;
  20. burnDamage?: number;
  21. returnSpeed?: number;
  22. homingStrength?: number;
  23. };
  24. bulletConfig: {
  25. bulletType: string;
  26. bulletPrefab: string;
  27. hitEffect: string;
  28. trailEffect?: string;
  29. ricochetCount?: number;
  30. ricochetAngle?: number;
  31. explosionDelay?: number;
  32. burnEffect?: string;
  33. arcHeight?: number;
  34. returnDelay?: number;
  35. homingDelay?: number;
  36. };
  37. attackPattern: {
  38. type: string;
  39. projectileCount: number;
  40. spreadAngle: number;
  41. burstCount: number;
  42. burstDelay: number;
  43. };
  44. visualConfig: {
  45. weaponSprites: {
  46. [size: string]: string;
  47. };
  48. muzzleFlash: string;
  49. fireSound: string;
  50. };
  51. }
  52. // 敌人配置接口
  53. export interface EnemyConfig {
  54. id: string;
  55. name: string;
  56. type: string;
  57. rarity: string;
  58. weight: number;
  59. stats: {
  60. health: number;
  61. speed: number;
  62. damage: number;
  63. attackRange: number;
  64. attackSpeed: number;
  65. defense: number;
  66. coinReward: number;
  67. explosionDamage?: number;
  68. explosionRadius?: number;
  69. };
  70. movement: {
  71. type: string;
  72. pattern: string;
  73. speedVariation: number;
  74. swayAmplitude?: number;
  75. swayFrequency?: number;
  76. };
  77. combat: {
  78. attackType: string;
  79. attackDelay: number;
  80. attackCooldown: number;
  81. weaponType?: string;
  82. projectileType?: string;
  83. projectileSpeed?: number;
  84. canBlock: boolean;
  85. blockChance: number;
  86. };
  87. visualConfig: {
  88. spritePrefab: string;
  89. animations: {
  90. [state: string]: string;
  91. };
  92. scale: number;
  93. flipX: boolean;
  94. weapon?: string;
  95. armor?: string;
  96. prop?: string;
  97. };
  98. audioConfig: {
  99. [sound: string]: string;
  100. };
  101. specialAbilities: string[];
  102. stealthConfig?: {
  103. stealthDuration: number;
  104. stealthCooldown: number;
  105. revealOnAttack: boolean;
  106. visibilityAlpha: number;
  107. };
  108. armorConfig?: {
  109. armorHealth: number;
  110. armorReduction: number;
  111. breakThreshold: number;
  112. };
  113. explosionConfig?: {
  114. explosionDelay: number;
  115. explosionEffect: string;
  116. damageRadius: number;
  117. knockbackForce: number;
  118. };
  119. bossConfig?: {
  120. phases: number;
  121. phaseHealthThreshold: number;
  122. enrageBonus?: {
  123. speed: number;
  124. damage: number;
  125. attackSpeed: number;
  126. };
  127. summonAbility?: {
  128. minionType: string;
  129. summonCount: number;
  130. summonCooldown: number;
  131. };
  132. laserAbility?: {
  133. damage: number;
  134. range: number;
  135. chargeTime: number;
  136. cooldown: number;
  137. };
  138. };
  139. projectileConfig?: {
  140. bulletPrefab: string;
  141. hitEffect: string;
  142. trailEffect?: string;
  143. };
  144. }
  145. @ccclass('ConfigManager')
  146. export class ConfigManager extends Component {
  147. private static instance: ConfigManager = null;
  148. private weaponsConfig: any = null;
  149. private enemiesConfig: any = null;
  150. private configLoaded: boolean = false;
  151. // 武器权重缓存
  152. private weaponWeightedList: WeaponConfig[] = [];
  153. // 敌人权重缓存
  154. private enemyWeightedList: EnemyConfig[] = [];
  155. onLoad() {
  156. if (ConfigManager.instance === null) {
  157. ConfigManager.instance = this;
  158. this.loadConfigs();
  159. } else if (ConfigManager.instance !== this) {
  160. this.destroy();
  161. return;
  162. }
  163. }
  164. onDestroy() {
  165. if (ConfigManager.instance === this) {
  166. ConfigManager.instance = null;
  167. }
  168. }
  169. public static getInstance(): ConfigManager {
  170. return ConfigManager.instance;
  171. }
  172. // 加载所有配置文件
  173. private async loadConfigs() {
  174. this.configLoaded = false;
  175. try {
  176. // 加载武器配置
  177. await this.loadWeaponsConfig();
  178. // 加载敌人配置
  179. await this.loadEnemiesConfig();
  180. this.configLoaded = true;
  181. } catch (error) {
  182. this.configLoaded = false;
  183. }
  184. }
  185. // 加载武器配置
  186. private loadWeaponsConfig(): Promise<void> {
  187. return new Promise((resolve, reject) => {
  188. console.log('加载武器配置...');
  189. resources.load('data/weapons', JsonAsset, (err, asset) => {
  190. if (err) {
  191. console.error('武器配置文件加载失败:', err);
  192. reject(err);
  193. return;
  194. }
  195. if (!asset || !asset.json) {
  196. console.error('武器配置文件内容为空');
  197. reject(new Error('武器配置文件内容为空'));
  198. return;
  199. }
  200. this.weaponsConfig = asset.json as any;
  201. console.log('✅ 武器配置加载成功');
  202. this.buildWeaponWeightedList();
  203. resolve();
  204. });
  205. });
  206. }
  207. // 加载敌人配置
  208. private loadEnemiesConfig(): Promise<void> {
  209. return new Promise((resolve, reject) => {
  210. console.log('加载敌人配置...');
  211. resources.load('data/enemies', JsonAsset, (err, asset) => {
  212. if (err) {
  213. console.error('敌人配置文件加载失败:', err);
  214. reject(err);
  215. return;
  216. }
  217. if (!asset || !asset.json) {
  218. console.error('敌人配置文件内容为空');
  219. reject(new Error('敌人配置文件内容为空'));
  220. return;
  221. }
  222. this.enemiesConfig = asset.json as any;
  223. console.log('✅ 敌人配置加载成功');
  224. this.buildEnemyWeightedList();
  225. resolve();
  226. });
  227. });
  228. }
  229. // 构建武器权重列表
  230. private buildWeaponWeightedList() {
  231. if (!this.weaponsConfig) return;
  232. this.weaponWeightedList = [];
  233. this.weaponsConfig.weapons.forEach(weapon => {
  234. // 根据权重添加多次到列表中
  235. for (let i = 0; i < weapon.weight; i++) {
  236. this.weaponWeightedList.push(weapon);
  237. }
  238. });
  239. console.log('武器权重列表构建完成,总权重:', this.weaponWeightedList.length);
  240. }
  241. // 构建敌人权重列表
  242. private buildEnemyWeightedList() {
  243. if (!this.enemiesConfig) return;
  244. this.enemyWeightedList = [];
  245. this.enemiesConfig.enemies.forEach(enemy => {
  246. // 根据权重添加多次到列表中
  247. for (let i = 0; i < enemy.weight; i++) {
  248. this.enemyWeightedList.push(enemy);
  249. }
  250. });
  251. console.log('敌人权重列表构建完成,总权重:', this.enemyWeightedList.length);
  252. }
  253. // 随机获取武器配置
  254. public getRandomWeapon(rarity?: string): WeaponConfig | null {
  255. if (!this.weaponsConfig || this.weaponWeightedList.length === 0) {
  256. console.warn('武器配置未加载或为空');
  257. return null;
  258. }
  259. if (rarity) {
  260. // 按稀有度筛选
  261. const filteredWeapons = this.weaponsConfig.weapons.filter(weapon => weapon.rarity === rarity);
  262. if (filteredWeapons.length === 0) {
  263. console.warn(`没有找到稀有度为 ${rarity} 的武器`);
  264. return null;
  265. }
  266. const randomIndex = Math.floor(Math.random() * filteredWeapons.length);
  267. return filteredWeapons[randomIndex];
  268. }
  269. // 从权重列表中随机选择
  270. const randomIndex = Math.floor(Math.random() * this.weaponWeightedList.length);
  271. return this.weaponWeightedList[randomIndex];
  272. }
  273. // 随机获取敌人配置
  274. public getRandomEnemy(rarity?: string): EnemyConfig | null {
  275. if (!this.enemiesConfig || this.enemyWeightedList.length === 0) {
  276. console.warn('敌人配置未加载或为空');
  277. return null;
  278. }
  279. if (rarity) {
  280. // 按稀有度筛选
  281. const filteredEnemies = this.enemiesConfig.enemies.filter(enemy => enemy.rarity === rarity);
  282. if (filteredEnemies.length === 0) {
  283. console.warn(`没有找到稀有度为 ${rarity} 的敌人`);
  284. return null;
  285. }
  286. const randomIndex = Math.floor(Math.random() * filteredEnemies.length);
  287. return filteredEnemies[randomIndex];
  288. }
  289. // 从权重列表中随机选择
  290. const randomIndex = Math.floor(Math.random() * this.enemyWeightedList.length);
  291. return this.enemyWeightedList[randomIndex];
  292. }
  293. // 根据ID获取武器配置
  294. public getWeaponById(id: string): WeaponConfig | null {
  295. if (!this.weaponsConfig) return null;
  296. return this.weaponsConfig.weapons.find(weapon => weapon.id === id) || null;
  297. }
  298. // 根据ID获取敌人配置
  299. public getEnemyById(id: string): EnemyConfig | null {
  300. if (!this.enemiesConfig) return null;
  301. return this.enemiesConfig.enemies.find(enemy => enemy.id === id) || null;
  302. }
  303. // 获取所有武器配置
  304. public getAllWeapons(): WeaponConfig[] {
  305. return this.weaponsConfig?.weapons || [];
  306. }
  307. // 获取所有敌人配置
  308. public getAllEnemies(): EnemyConfig[] {
  309. return this.enemiesConfig?.enemies || [];
  310. }
  311. // 根据稀有度获取武器列表
  312. public getWeaponsByRarity(rarity: string): WeaponConfig[] {
  313. if (!this.weaponsConfig) return [];
  314. return this.weaponsConfig.weapons.filter(weapon => weapon.rarity === rarity);
  315. }
  316. // 根据稀有度获取敌人列表
  317. public getEnemiesByRarity(rarity: string): EnemyConfig[] {
  318. if (!this.enemiesConfig) return [];
  319. return this.enemiesConfig.enemies.filter(enemy => enemy.rarity === rarity);
  320. }
  321. // 获取方块尺寸列表
  322. public getBlockSizes(): string[] {
  323. return this.weaponsConfig?.blockSizes || ['1x1', '1x2', '2x1', '2x2'];
  324. }
  325. // 获取波次进展配置
  326. public getWaveProgression(): any {
  327. return this.enemiesConfig?.waveProgression || {};
  328. }
  329. // 根据波次获取合适的敌人
  330. public getEnemyForWave(waveNumber: number): EnemyConfig | null {
  331. if (!this.enemiesConfig) return null;
  332. const progression = this.enemiesConfig.waveProgression;
  333. let enemyPool: string[] = [];
  334. if (waveNumber <= 5) {
  335. enemyPool = progression.earlyWaves || [];
  336. } else if (waveNumber <= 15) {
  337. enemyPool = [...(progression.earlyWaves || []), ...(progression.midWaves || [])];
  338. } else if (waveNumber <= 25) {
  339. enemyPool = [...(progression.midWaves || []), ...(progression.lateWaves || [])];
  340. } else {
  341. enemyPool = [...(progression.lateWaves || []), ...(progression.bossWaves || [])];
  342. }
  343. if (enemyPool.length === 0) {
  344. return this.getRandomEnemy();
  345. }
  346. const randomId = enemyPool[Math.floor(Math.random() * enemyPool.length)];
  347. return this.getEnemyById(randomId);
  348. }
  349. // 检查配置是否已加载
  350. public isConfigLoaded(): boolean {
  351. return this.configLoaded;
  352. }
  353. }