/** * 肉鸽模式配置脚本 * * 功能说明: * - 提供肉鸽模式的波次生成配置 * - 包含词条系统和怪物强化逻辑 * - 供 MissionMonComp.ts 等组件调用 * * 波次规则(固定9波模式): * - 1-3波:普通波次 * - 4-6波:怪物潮波次(大量低级怪物) * - 7-8波:精英波次 * - 9波:最终Boss波次 * * @author 游戏开发团队 * @version 2.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", // 普通波次(1-3波) HORDE = "horde", // 怪物潮波次(4-6波) ELITE = "elite", // 精英波次(7-8波) FINAL_BOSS = "final_boss" // 最终Boss波次(9波) } //波次和天赋对应关系 export const RogueTalWave = { 0:{tal_slot_key:0,wave:1}, 1:{tal_slot_key:1,wave:2}, 2:{tal_slot_key:2,wave:3}, 3:{tal_slot_key:3,wave:4}, 4:{tal_slot_key:4,wave:5}, 5:{tal_slot_key:5,wave:6}, } /** * 固定数值配置(根据波次固定血量和攻击力) */ export const RogueStatsConfig = { // 血量配置 hp: { 1: 10, // 波次1:小怪血量10 2: 15, // 波次2:小怪血量15(插值) 3: 25, // 波次3:小怪血量25 4: 35, // 波次4:怪物潮血量35(插值) 5: 60, // 波次5:怪物潮血量60 6: 80, // 波次6:怪物潮血量80(插值) 7: 100, // 波次7:精英血量100 8: 150, // 波次8:精英血量150(插值) 9: 500 // 波次9:boss血量500 }, // 攻击力配置 attack: { 1: 5, // 1-3波:攻击力5 2: 5, // 1-3波:攻击力5 3: 5, // 1-3波:攻击力5 4: 8, // 4-6波:攻击力8 5: 8, // 4-6波:攻击力8 6: 8, // 4-6波:攻击力8 7: 12, // 7-8波:攻击力12 8: 12, // 7-8波:攻击力12 9: 30 // 9波boss:攻击力30 }, /** * 获取指定波次的血量 */ getHp(waveNumber: number): number { return this.hp[waveNumber] || this.hp[9]; // 默认返回boss血量 }, /** * 获取指定波次的攻击力 */ getAttack(waveNumber: number): number { return this.attack[waveNumber] || this.attack[9]; // 默认返回boss攻击力 } }; /** * 怪物词条配置(直接使用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] } }; /** * 词条数量配置(9波固定模式) */ export const AffixCountConfig = { currentMode: "normal" as "normal" | "enhanced", modes: { normal: { [RogueWaveType.NORMAL]: 0, // 1-3波:无词条 [RogueWaveType.HORDE]: 0, // 4-6波:无词条(数量取胜) [RogueWaveType.ELITE]: 1, // 7-8波:1个词条 [RogueWaveType.FINAL_BOSS]: 2, // 9波:2个词条 }, enhanced: { [RogueWaveType.NORMAL]: 1, // 1-3波:1个词条 [RogueWaveType.HORDE]: 1, // 4-6波:1个词条 [RogueWaveType.ELITE]: 2, // 7-8波:2个词条 [RogueWaveType.FINAL_BOSS]: 3, // 9波: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"); } }; /** * 波次配置(固定9波模式) */ export const RogueWaveConfig = { // 固定9波模式,每波类型固定 getWaveType: (waveNumber: number): RogueWaveType => { if (waveNumber <= 3) { return RogueWaveType.NORMAL; // 1-3波:普通 } else if (waveNumber <= 6) { return RogueWaveType.HORDE; // 4-6波:怪物潮 } else if (waveNumber <= 8) { return RogueWaveType.ELITE; // 7-8波:精英 } else if (waveNumber === 9) { return RogueWaveType.FINAL_BOSS; // 9波:最终Boss } else { // 超过9波的情况(如果需要循环) const cycleWave = ((waveNumber - 1) % 9) + 1; return RogueWaveConfig.getWaveType(cycleWave); } }, maxWaves: 9 // 固定最大波数 }; // ==================== 肉鸽配置生成器 ==================== /** * 肉鸽配置生成器 */ export class RogueConfig { /** * 生成波次配置(主入口) */ static generateWaveConfig(waveNumber: number) { const waveType = RogueWaveConfig.getWaveType(waveNumber); const fixedHp = RogueStatsConfig.getHp(waveNumber); const fixedAttack = RogueStatsConfig.getAttack(waveNumber); console.log(`[RogueConfig]: 第${waveNumber}波 - 类型: ${waveType} - 固定HP: ${fixedHp}, 固定攻击: ${fixedAttack} (固定9波模式)`); // 根据类型生成配置 switch (waveType) { case RogueWaveType.NORMAL: return this.generateNormalWave(waveNumber); case RogueWaveType.HORDE: return this.generateHordeWave(waveNumber); case RogueWaveType.ELITE: return this.generateEliteWave(waveNumber); case RogueWaveType.FINAL_BOSS: return this.generateFinalBossWave(waveNumber); default: return this.generateNormalWave(waveNumber); } } /** * 生成普通波次(1-3波) */ static generateNormalWave(waveNumber: number) { const series = getRandomSeries(); const seriesConfig = MonsterSeriesConfig[series]; // 普通波次固定数量:10个怪物 const baseCount = 10; 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, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); } return { waveType: RogueWaveType.NORMAL, monsters: monsters, description: `第${waveNumber}波 - 普通波次 (10个怪物)`, waveNumber: waveNumber }; } /** * 生成怪物潮波次(4-6波) */ static generateHordeWave(waveNumber: number) { const series = getRandomSeries(); const seriesConfig = MonsterSeriesConfig[series]; // 怪物潮固定数量:20个怪物 const baseCount = 20; const monsters = []; // 怪物潮主要使用绿色品质的小怪 const hordeMonsters = seriesConfig.allMonsters.filter(uuid => { return HeroInfo[uuid] && HeroInfo[uuid].quality === HQuality.GREEN; }); if (hordeMonsters.length > 0) { const hordeMonster = hordeMonsters[Math.floor(Math.random() * hordeMonsters.length)]; const monsterInfo = HeroInfo[hordeMonster]; // 生成词条(怪物潮通常没有词条,靠数量取胜) const affixes = this.generateMonsterAffixes( monsterInfo.quality, waveNumber, RogueWaveType.HORDE ); const enhanced = this.applyAffixesToMonster(affixes, monsterInfo); monsters.push({ uuid: hordeMonster, count: baseCount, type: "warrior", series: series, isHorde: true, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); } else { // 如果没有绿色怪物,使用其他怪物 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.HORDE ); const enhanced = this.applyAffixesToMonster(affixes, monsterInfo); monsters.push({ uuid: randomMonster, count: baseCount, type: randomType, series: series, isHorde: true, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); } } return { waveType: RogueWaveType.HORDE, monsters: monsters, description: `第${waveNumber}波 - 怪物潮 (20个怪物)`, waveNumber: waveNumber }; } /** * 生成精英波次(7-8波) */ static generateEliteWave(waveNumber: number) { const series = getRandomSeries(); const seriesConfig = MonsterSeriesConfig[series]; const monsters = []; // 1. 生成5个精英怪物 const eliteMonsters = seriesConfig.allMonsters.filter(uuid => { return HeroInfo[uuid] && HeroInfo[uuid].quality === HQuality.BLUE; }); if (eliteMonsters.length > 0) { const eliteMonster = eliteMonsters[Math.floor(Math.random() * eliteMonsters.length)]; const monsterInfo = HeroInfo[eliteMonster]; // 生成精英词条 const affixes = this.generateMonsterAffixes( monsterInfo.quality, waveNumber, RogueWaveType.ELITE ); const enhanced = this.applyAffixesToMonster(affixes, monsterInfo); monsters.push({ uuid: eliteMonster, count: 5, // 固定5个精英 type: "elite", series: series, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); } // 2. 生成10个普通小怪 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: 10, // 固定10个小怪 type: "normal", series: series, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); } return { waveType: RogueWaveType.ELITE, monsters: monsters, description: `第${waveNumber}波 - 精英波次 (5个精英+10个小怪)`, waveNumber: waveNumber }; } /** * 生成最终Boss波次(第9波) */ static generateFinalBossWave(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.FINAL_BOSS ); const enhancedBoss = this.applyAffixesToMonster(bossAffixes, bossInfo); // 1个Boss + 5个小怪 const monsters = []; // 1. 添加Boss monsters.push({ uuid: bossMonster, count: 1, type: "final_boss", series: series, isFinalBoss: true, affixes: bossAffixes, enhancedStats: enhancedBoss.stats, buffData: enhancedBoss.buffData, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); // 2. 添加5个小怪 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: 5, // 固定5个小怪 type: "normal", series: series, affixes: affixes, enhancedStats: enhanced.stats, buffData: enhanced.buffData, // 肉鸽固定数值 rogueHp: RogueStatsConfig.getHp(waveNumber), rogueAttack: RogueStatsConfig.getAttack(waveNumber) }); } return { waveType: RogueWaveType.FINAL_BOSS, monsters: monsters, description: `第${waveNumber}波 - 最终Boss战 (1个Boss+5个小怪)`, 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 = []; // 怪物能力提升倍数(3倍强化) const enhancementMultiplier = 3; for (const affix of affixes) { const config = MonsterAffixConfig[affix]; if (config) { // 应用3倍强化到配置值 const enhancedValue = config.value * enhancementMultiplier; buffData.push({ buff_type: affix, value: enhancedValue // 使用强化后的值 }); // 预览属性变化(实际应用在Mon.ts中) switch (affix) { case BuffAttr.ATK: // 攻击力提升幅度加大,每波提升额外增加10%,再乘以3倍 modifiedStats.ap = Math.floor(modifiedStats.ap * (1 + enhancedValue / 100 + baseStats.lv * 0.1 * enhancementMultiplier)); break; case BuffAttr.HP: // 生命值提升幅度加大,每波提升额外增加15%,再乘以3倍 modifiedStats.hp = Math.floor(modifiedStats.hp * (1 + enhancedValue / 100 + baseStats.lv * 0.15 * enhancementMultiplier)); break; case BuffAttr.ATK_CD: // 攻击速度提升也应用3倍效果 modifiedStats.cd = Math.max(0.1, modifiedStats.cd * (1 - enhancedValue / 100)); break; case BuffAttr.DEF: // 防御力提升3倍效果 modifiedStats.def = (modifiedStats.def || 0) + enhancedValue; break; case BuffAttr.CRITICAL: // 暴击率提升3倍效果 modifiedStats.crit = (modifiedStats.crit || 0) + enhancedValue; break; case BuffAttr.CRITICAL_DMG: // 暴击伤害提升3倍效果 modifiedStats.crit_d = (modifiedStats.crit_d || 0) + enhancedValue; break; case BuffAttr.DODGE: // 闪避率提升3倍效果 modifiedStats.dod = (modifiedStats.dod || 0) + enhancedValue; break; case BuffAttr.BURN_COUNT: // 燃烧次数提升3倍效果 modifiedStats.burn_count = (modifiedStats.burn_count || 0) + enhancedValue; break; case BuffAttr.PUNCTURE: // 穿刺数量提升3倍效果 modifiedStats.puncture = (modifiedStats.puncture || 0) + enhancedValue; break; case BuffAttr.FROST_RATIO: // 冰冻概率提升3倍效果 modifiedStats.frost_ratto = (modifiedStats.frost_ratto || 0) + enhancedValue; break; } console.log(`[RogueConfig]: 应用3倍强化词条 ${BuffAttr[affix]} - 原始值: ${config.value}% → 强化值: ${enhancedValue}%`); } } return { stats: modifiedStats, buffData: buffData, // 返回Buff数据格式,与Mon.ts兼容 affixes: affixes }; } /** * 获取怪物等级 */ static getMonsterLevel(waveNumber: number): number { return Math.max(1, Math.floor(waveNumber / 1) + 1); } } // ==================== 导出接口 ==================== /** * 外部调用接口 - 获取波次配置 */ export const getRogueWaveConfig = (waveNumber: number) => { return RogueConfig.generateWaveConfig(waveNumber); };