/** * 肉鸽模式配置脚本 * * 功能说明: * - 提供肉鸽模式的波次生成配置 * - 包含词条系统和怪物强化逻辑 * - 供 MissionMonComp.ts 等组件调用 * * 波次规则: * - 固定波次:5(商店)、10(Boss)、15(休息)、20(Boss)、25(商店)、30(Boss) * - 精英波次:个位数是4和9的波次(4、9、14、19、24、29...) * - 普通波次:其他所有波次 * * @author 游戏开发团队 * @version 1.0 * @date 2025-07-12 */ // 导入配置 import { HQuality, HeroInfo, MonsterSeriesConfig, getRandomSeries } from "../common/config/heroSet"; import { BuffAttr } from "../common/config/SkillSet"; // ==================== 核心配置 ==================== /** * 肉鸽模式波次类型枚举 */ export enum RogueWaveType { NORMAL = "normal", ELITE = "elite", BOSS = "boss", SHOP = "shop", REST = "rest" } /** * 怪物词条配置(直接使用BuffAttr作为词条类型) * 这样可以直接复用Mon.ts中的Buff处理逻辑 */ export const MonsterAffixConfig = { [BuffAttr.ATK]: { name: "狂暴", description: "攻击力提升50%", value: 50, rarity: "common", applicableQualities: [HQuality.GREEN, HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.ATK_CD]: { name: "迅捷", description: "攻击速度提升30%", value: 30, // 正值表示提升,Mon.ts中会转换为负值 rarity: "common", applicableQualities: [HQuality.GREEN, HQuality.BLUE] }, [BuffAttr.CRITICAL]: { name: "致命", description: "暴击率提升25%", value: 25, rarity: "uncommon", applicableQualities: [HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.DEF]: { name: "装甲", description: "减少受到的伤害30%", value: 30, rarity: "common", applicableQualities: [HQuality.GREEN, HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.HP]: { name: "坚韧", description: "生命值提升50%", value: 50, rarity: "common", applicableQualities: [HQuality.GREEN, HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.CRITICAL_DMG]: { name: "嗜血", description: "暴击伤害提升40%", value: 40, rarity: "uncommon", applicableQualities: [HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.DODGE]: { name: "敏捷", description: "闪避率提升25%", value: 25, rarity: "uncommon", applicableQualities: [HQuality.GREEN, HQuality.BLUE] }, [BuffAttr.BURN_COUNT]: { name: "燃烧", description: "攻击附带易伤效果,额外持续3次", value: 3, rarity: "uncommon", applicableQualities: [HQuality.GREEN, HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.PUNCTURE]: { name: "穿刺", description: "攻击穿透1个敌人", value: 1, rarity: "uncommon", applicableQualities: [HQuality.BLUE, HQuality.PURPLE] }, [BuffAttr.FROST_RATIO]: { name: "冰冻", description: "攻击有20%概率冰冻敌人", value: 20, rarity: "rare", applicableQualities: [HQuality.BLUE, HQuality.PURPLE] } }; /** * 词条数量配置 */ export const AffixCountConfig = { currentMode: "normal" as "normal" | "enhanced", modes: { normal: { [RogueWaveType.NORMAL]: 0, [RogueWaveType.ELITE]: 1, [RogueWaveType.BOSS]: 2, }, enhanced: { [RogueWaveType.NORMAL]: 1, [RogueWaveType.ELITE]: 2, [RogueWaveType.BOSS]: 3, } }, setMode(mode: "normal" | "enhanced") { this.currentMode = mode; }, getAffixCount(waveType: RogueWaveType): number { return this.modes[this.currentMode][waveType] || 0; }, enableNormalMode() { this.setMode("normal"); }, enableEnhancedMode() { this.setMode("enhanced"); } }; /** * 波次配置 */ export const RogueWaveConfig = { fixedWaves: { 5: RogueWaveType.SHOP, 10: RogueWaveType.BOSS, 15: RogueWaveType.REST, 20: RogueWaveType.BOSS, 25: RogueWaveType.SHOP, 30: RogueWaveType.BOSS }, isEliteWave: (waveNumber: number): boolean => { const lastDigit = waveNumber % 10; return lastDigit === 4 || lastDigit === 9; } }; // ==================== 肉鸽配置生成器 ==================== /** * 肉鸽配置生成器 */ export class RogueConfig { /** * 生成波次配置(主入口) */ static generateWaveConfig(waveNumber: number) { let waveType: RogueWaveType; // 判断波次类型 if (RogueWaveConfig.fixedWaves[waveNumber]) { waveType = RogueWaveConfig.fixedWaves[waveNumber]; } else if (RogueWaveConfig.isEliteWave(waveNumber)) { waveType = RogueWaveType.ELITE; } else { waveType = RogueWaveType.NORMAL; } console.log(`[RogueConfig]: 第${waveNumber}波 - 类型: ${waveType}`); // 根据类型生成配置 switch (waveType) { case RogueWaveType.NORMAL: return this.generateNormalWave(waveNumber); case RogueWaveType.ELITE: return this.generateEliteWave(waveNumber); case RogueWaveType.BOSS: return this.generateBossWave(waveNumber); case RogueWaveType.SHOP: return this.generateShopWave(waveNumber); case RogueWaveType.REST: return this.generateRestWave(waveNumber); default: return this.generateNormalWave(waveNumber); } } /** * 生成普通波次 */ static generateNormalWave(waveNumber: number) { const series = getRandomSeries(); const seriesConfig = MonsterSeriesConfig[series]; const baseCount = Math.min(3 + Math.floor(waveNumber / 5), 8); const monsters = []; // 选择怪物类型 const availableTypes = []; if (seriesConfig.monsters.warrior.length > 0) availableTypes.push("warrior"); if (seriesConfig.monsters.remote.length > 0) availableTypes.push("remote"); if (seriesConfig.monsters.mage.length > 0) availableTypes.push("mage"); if (availableTypes.length > 0) { const randomType = availableTypes[Math.floor(Math.random() * availableTypes.length)]; const typeMonsters = seriesConfig.monsters[randomType]; const randomMonster = typeMonsters[Math.floor(Math.random() * typeMonsters.length)]; const monsterInfo = HeroInfo[randomMonster]; // 生成词条 const affixes = this.generateMonsterAffixes( monsterInfo.quality, waveNumber, RogueWaveType.NORMAL ); // 应用强化 const enhanced = this.applyAffixesToMonster(affixes, monsterInfo); monsters.push({ uuid: randomMonster, count: baseCount, type: randomType, series: series, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData }); } return { waveType: RogueWaveType.NORMAL, monsters: monsters, description: `普通波次 - ${seriesConfig.name}`, waveNumber: waveNumber }; } /** * 生成精英波次 */ static generateEliteWave(waveNumber: number) { const series = getRandomSeries(); const seriesConfig = MonsterSeriesConfig[series]; // 查找精英怪物 const eliteMonsters = seriesConfig.allMonsters.filter(uuid => { return HeroInfo[uuid] && HeroInfo[uuid].quality === HQuality.BLUE; }); const monsters = []; if (eliteMonsters.length > 0) { const eliteMonster = eliteMonsters[Math.floor(Math.random() * eliteMonsters.length)]; const count = Math.max(1, Math.floor(2 + waveNumber / 8)); const monsterInfo = HeroInfo[eliteMonster]; // 生成精英词条 const affixes = this.generateMonsterAffixes( monsterInfo.quality, waveNumber, RogueWaveType.ELITE ); const enhanced = this.applyAffixesToMonster(affixes, monsterInfo); monsters.push({ uuid: eliteMonster, count: count, type: "warrior", series: series, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData }); } return { waveType: RogueWaveType.ELITE, monsters: monsters, description: `精英波次 - ${seriesConfig.name}精锐`, waveNumber: waveNumber }; } /** * 生成Boss波次 */ static generateBossWave(waveNumber: number) { const series = getRandomSeries(); const seriesConfig = MonsterSeriesConfig[series]; // 查找Boss怪物 const bossMonsters = seriesConfig.allMonsters.filter(uuid => { return HeroInfo[uuid] && HeroInfo[uuid].quality === HQuality.PURPLE; }); const bossMonster = bossMonsters.length > 0 ? bossMonsters[Math.floor(Math.random() * bossMonsters.length)] : seriesConfig.allMonsters[Math.floor(Math.random() * seriesConfig.allMonsters.length)]; const bossInfo = HeroInfo[bossMonster]; // 生成Boss词条 const bossAffixes = this.generateMonsterAffixes( bossInfo.quality, waveNumber, RogueWaveType.BOSS ); const enhancedBoss = this.applyAffixesToMonster(bossAffixes, bossInfo); const monsters = [{ uuid: bossMonster, count: 1, type: "boss", series: series, isBoss: true, affixes: bossAffixes, enhancedStats: enhancedBoss.stats, buffData: enhancedBoss.buffData }]; return { waveType: RogueWaveType.BOSS, monsters: monsters, description: `Boss战 - ${seriesConfig.name}首领`, waveNumber: waveNumber }; } /** * 生成商店波次 */ static generateShopWave(waveNumber: number) { return { waveType: RogueWaveType.SHOP, description: "商店波次", waveNumber: waveNumber }; } /** * 生成休息波次 */ static generateRestWave(waveNumber: number) { return { waveType: RogueWaveType.REST, description: "休息波次", waveNumber: waveNumber }; } /** * 生成怪物词条(现在直接返回BuffAttr数组) */ static generateMonsterAffixes( monsterQuality: number, waveNumber: number, waveType: RogueWaveType ): BuffAttr[] { const affixCount = AffixCountConfig.getAffixCount(waveType); if (affixCount === 0) return []; const availableAffixes = Object.keys(MonsterAffixConfig).filter(affixType => { const buffAttr = parseInt(affixType) as BuffAttr; const config = MonsterAffixConfig[buffAttr]; return config.applicableQualities.includes(monsterQuality); }).map(key => parseInt(key) as BuffAttr); const selectedAffixes: BuffAttr[] = []; for (let i = 0; i < affixCount && availableAffixes.length > 0; i++) { const randomIndex = Math.floor(Math.random() * availableAffixes.length); const selectedAffix = availableAffixes[randomIndex]; selectedAffixes.push(selectedAffix); availableAffixes.splice(randomIndex, 1); } return selectedAffixes; } /** * 应用词条到怪物(简化版本,主要用于日志显示) */ static applyAffixesToMonster(affixes: BuffAttr[], baseStats: any) { const modifiedStats = { ...baseStats }; const buffData = []; for (const affix of affixes) { const config = MonsterAffixConfig[affix]; if (config) { buffData.push({ buff_type: affix, value: config.value }); // 预览属性变化(实际应用在Mon.ts中) switch (affix) { case BuffAttr.ATK: modifiedStats.ap = Math.floor(modifiedStats.ap * (1 + config.value / 100)); break; case BuffAttr.HP: modifiedStats.hp = Math.floor(modifiedStats.hp * (1 + config.value / 100)); break; case BuffAttr.ATK_CD: modifiedStats.cd = Math.max(0.1, modifiedStats.cd * (1 - config.value / 100)); break; } } } return { stats: modifiedStats, buffData: buffData, // 返回Buff数据格式,与Mon.ts兼容 affixes: affixes }; } /** * 获取怪物等级 */ static getMonsterLevel(waveNumber: number): number { return Math.max(1, Math.floor(waveNumber / 5) + 1); } } // ==================== 导出接口 ==================== /** * 外部调用接口 - 获取波次配置 */ export const getRogueWaveConfig = (waveNumber: number) => { return RogueConfig.generateWaveConfig(waveNumber); };