Files
pixelheros/assets/script/game/map/RogueConfig.ts
panw 63dd22fb88 refactor: 重命名Logger类并增加错误日志方法
- 将Logger类重命名为mLogger以符合命名规范
- 新增error方法用于统一错误输出
- 在多个组件中替换console.log/warn/error为mLogger的对应方法
- 为多个组件添加debugMode属性以控制模块级日志开关
- 新增HeroMasterComp组件框架
2026-02-03 14:40:02 +08:00

356 lines
11 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 肉鸽模式配置脚本 - 增强版 (Wave System)
*
* 功能说明:
* - 采用 15 个小波次(每分钟 1 波)
* - 整合进 3 个大的节奏阶段:构筑期、磨合期、极限期
* - 废弃动态预算,使用确定性波次配置
*
* @author 游戏开发团队
* @version 3.0 波次重构版
* @date 2025-10-19
*/
import { HeroInfo } from "../common/config/heroSet";
import { mLogger } from "../common/Logger";
/**
* 怪物类型枚举
*/
export enum MonType {
NORMAL = 0, // 普通怪物
ELITE = 1, // 精英怪物
BOSS = 2 // Boss怪物
}
/**
* 怪物配置接口 (用于生成实例)
*/
export interface IMonsConfig {
uuid: number; // 怪物ID
type: MonType; // 怪物类型
level: number; // 等级
position?: number; // 位置(可选)
buffs?: any[]; // buff列表可选
}
/**
* 怪物属性接口
*/
export interface MonAttrs {
hp: number;
mp: number;
ap: number;
def: number;
speed: number;
exp?: number;
gold?: number;
}
/**
* 成长类型枚举
*/
enum GrowthType {
EXPONENTIAL = 1.15, // 指数级 - HP
LINEAR = 1.05, // 线性 - AP
LOGARITHMIC = 0.3 // 对数级 - Speed
}
/**
* 刷怪权重接口
*/
export interface SpawnWeight {
uuid: number;
weight: number;
type?: MonType; // 默认为 NORMAL
}
/**
* 波次配置接口
*/
export interface WaveConfig {
waveId: number; // 波次ID (1-15)
name: string; // 波次名称
duration: number; // 持续时间 (秒)通常为60
spawnInterval: number; // 刷怪间隔 (秒)
maxActive: number; // 同屏最大怪物数
weights: SpawnWeight[]; // 怪物权重池
}
// 怪物ID映射 (方便阅读)
const MON_IDS = {
WARRIOR: 5201, // 战士
ASSASSIN: 5301, // 斥候
TANK: 5401, // 卫士
ARCHER: 5501, // 射手
BOMBER: 5601, // 自爆兵
SUMMONER: 5602, // 召唤师
HEALER: 5603, // 祭司
TOTEM: 5604, // 图腾师
BOSS: 5701 // 首领
};
/**
* 全局波次配置表 (15波)
*/
export const RogueWaves: WaveConfig[] = [
// --- 第一阶段:构筑期 (0-5min) ---
{
waveId: 1, name: "热身", duration: 60, spawnInterval: 2.0, maxActive: 5,
weights: [{ uuid: MON_IDS.WARRIOR, weight: 100 }]
},
{
waveId: 2, name: "加速", duration: 60, spawnInterval: 1.8, maxActive: 6,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 80 },
{ uuid: MON_IDS.ASSASSIN, weight: 20 }
]
},
{
waveId: 3, name: "堆叠", duration: 60, spawnInterval: 1.6, maxActive: 7,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 60 },
{ uuid: MON_IDS.ASSASSIN, weight: 40 }
]
},
{
waveId: 4, name: "硬度测试", duration: 60, spawnInterval: 1.5, maxActive: 8,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 50 },
{ uuid: MON_IDS.ASSASSIN, weight: 30 },
{ uuid: MON_IDS.TANK, weight: 20 }
]
},
{
waveId: 5, name: "精英首秀", duration: 60, spawnInterval: 1.5, maxActive: 8,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 40 },
{ uuid: MON_IDS.ASSASSIN, weight: 40 },
{ uuid: MON_IDS.TANK, weight: 20 }
// 注意第5分钟会触发固定事件刷精英怪这里只配普通怪
]
},
// --- 第二阶段:磨合期 (5-10min) ---
{
waveId: 6, name: "远程威胁", duration: 60, spawnInterval: 1.4, maxActive: 10,
weights: [
{ uuid: MON_IDS.TANK, weight: 30 },
{ uuid: MON_IDS.ARCHER, weight: 40 },
{ uuid: MON_IDS.WARRIOR, weight: 30 }
]
},
{
waveId: 7, name: "铁桶阵", duration: 60, spawnInterval: 1.3, maxActive: 10,
weights: [
{ uuid: MON_IDS.TANK, weight: 50 },
{ uuid: MON_IDS.ARCHER, weight: 50 }
]
},
{
waveId: 8, name: "续航干扰", duration: 60, spawnInterval: 1.2, maxActive: 12,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 30 },
{ uuid: MON_IDS.TANK, weight: 20 },
{ uuid: MON_IDS.ARCHER, weight: 30 },
{ uuid: MON_IDS.HEALER, weight: 20 }
]
},
{
waveId: 9, name: "走位测试", duration: 60, spawnInterval: 1.2, maxActive: 12,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 40 },
{ uuid: MON_IDS.BOMBER, weight: 30 }, // 自爆兵
{ uuid: MON_IDS.ARCHER, weight: 30 }
]
},
{
waveId: 10, name: "中场Boss", duration: 60, spawnInterval: 5.0, maxActive: 3,
// Boss战期间只刷少量护卫Boss由事件触发
weights: [
{ uuid: MON_IDS.TANK, weight: 100 }
]
},
// --- 第三阶段:极限期 (10-15min) ---
{
waveId: 11, name: "混乱开端", duration: 60, spawnInterval: 1.0, maxActive: 15,
weights: [
{ uuid: MON_IDS.SUMMONER, weight: 20 },
{ uuid: MON_IDS.TOTEM, weight: 20 },
{ uuid: MON_IDS.WARRIOR, weight: 30 },
{ uuid: MON_IDS.ARCHER, weight: 30 }
]
},
{
waveId: 12, name: "全家桶", duration: 60, spawnInterval: 0.9, maxActive: 18,
weights: [
{ uuid: MON_IDS.WARRIOR, weight: 15 },
{ uuid: MON_IDS.ASSASSIN, weight: 15 },
{ uuid: MON_IDS.TANK, weight: 15 },
{ uuid: MON_IDS.ARCHER, weight: 15 },
{ uuid: MON_IDS.BOMBER, weight: 15 },
{ uuid: MON_IDS.HEALER, weight: 10 },
{ uuid: MON_IDS.SUMMONER, weight: 15 }
]
},
{
waveId: 13, name: "精英小队", duration: 60, spawnInterval: 1.0, maxActive: 15,
weights: [
{ uuid: MON_IDS.TANK, weight: 40 },
{ uuid: MON_IDS.ARCHER, weight: 40 },
{ uuid: MON_IDS.WARRIOR, weight: 20, type: MonType.ELITE } // 尝试混入精英
]
},
{
waveId: 14, name: "绝地求生", duration: 60, spawnInterval: 0.6, maxActive: 20,
weights: [
{ uuid: MON_IDS.ASSASSIN, weight: 50 },
{ uuid: MON_IDS.BOMBER, weight: 50 }
]
},
{
waveId: 15, name: "终局", duration: 60, spawnInterval: 3.0, maxActive: 5,
// 最终Boss战只刷少量精英护卫
weights: [
{ uuid: MON_IDS.TANK, weight: 100, type: MonType.ELITE }
]
}
];
// 精英怪和Boss刷新时间配置 (时间单位: 秒)
// 注意:这里的时间点应与波次结束/开始对应
export const SpecialMonsterSchedule = [
{ time: 4 * 60 + 50, uuid: MON_IDS.WARRIOR, type: MonType.ELITE, level: 5, desc: "5分钟前夕: 精英战士" },
{ time: 9 * 60 + 55, uuid: MON_IDS.BOSS, type: MonType.BOSS, level: 15, desc: "10分钟: 兽人首领" },
{ time: 14 * 60 + 55, uuid: MON_IDS.BOSS, type: MonType.BOSS, level: 30, desc: "15分钟: 最终Boss" }
];
/**
* 获取当前时间的波次配置
* @param timeInSeconds 游戏时间 (秒)
*/
export function getCurrentWave(timeInSeconds: number): WaveConfig {
const waveIndex = Math.min(Math.floor(timeInSeconds / 60), 14);
return RogueWaves[waveIndex];
}
/**
* 怪物消耗点数配置 (用于经验/金币计算)
*/
export const MonsterCost: Record<number, number> = {
5201: 1, // 兽人战士 (Warrior)
5301: 3, // 兽人斥候 (Assassin)
5401: 5, // 兽人卫士 (Tank)
5501: 4, // 兽人射手 (Remote)
5601: 10, // 兽人自爆兵 (Mechanic)
5602: 8, // 兽人召唤师
5603: 6, // 兽人祭司 (Healer)
5604: 6, // 兽人图腾师
5701: 50, // 兽人首领 (Elite/Boss)
};
/**
* 计算波次因子
* @param stage 当前波次
* @param timeInSeconds 游戏进行时间(秒)
* @returns 波次因子 (0-1之间15分钟时达到最大)
*/
function calculateWaveFactor(stage: number, timeInSeconds: number = 0): number {
const MAX_GAME_TIME = 15 * 60; // 15分钟 = 900秒
const effectiveTime = timeInSeconds || (stage * 60);
const factor = Math.min(effectiveTime / MAX_GAME_TIME, 1.0);
return factor;
}
/**
* 应用成长公式到基础属性
*/
function applyGrowthFormula(baseStat: number, waveFactor: number, growthType: GrowthType): number {
// 基础倍率15分钟成长约 21 倍 (1 + 1.0 * 20)
const TIME_SCALING = 20;
const growthMultiplier = Math.pow(1 + waveFactor * TIME_SCALING, growthType);
return Math.floor(baseStat * growthMultiplier);
}
/**
* 获取怪物动态成长属性
* @param stage 当前波次 (这里复用为等级或忽略)
* @param uuid 怪物ID
* @param monType 怪物类型
* @param timeInSeconds 游戏进行时间(秒)
* @returns 怪物属性
*/
export function getMonAttr(stage: number, uuid: number, monType: MonType = MonType.NORMAL, timeInSeconds: number = 0): MonAttrs {
const baseMonster = HeroInfo[uuid];
if (!baseMonster) {
mLogger.warn(true, 'RogueConfig', `[RogueConfig] 未找到怪物ID: ${uuid}`);
return { hp: 100, mp: 100, ap: 10, def: 0, speed: 100 };
}
// 计算波次因子
const waveFactor = calculateWaveFactor(0, timeInSeconds);
// 动态质量系数:初始 1.5倍 -> 15分钟 6.0倍
// 大幅降低初始强度(原固定5.0),随时间线性增强
const qualityRatio = 1.5 + (4.5 * waveFactor);
// 根据怪物类型应用额外的倍率
let typeMultiplier = 1.0;
if (monType === MonType.ELITE) {
typeMultiplier = 2.0; // 精英怪2倍属性
} else if (monType === MonType.BOSS) {
typeMultiplier = 5.0; // Boss 5倍属性
}
// 应用不同的成长类型 (应用质量系数)
const hp = applyGrowthFormula(baseMonster.hp, waveFactor, GrowthType.EXPONENTIAL) * typeMultiplier * qualityRatio;
const ap = applyGrowthFormula(baseMonster.ap, waveFactor, GrowthType.LINEAR) * typeMultiplier * qualityRatio;
const speed = applyGrowthFormula(baseMonster.speed, waveFactor, GrowthType.LOGARITHMIC);
// MP和DEF使用线性成长 (应用质量系数)
const mp = applyGrowthFormula(baseMonster.mp, waveFactor, GrowthType.LINEAR) * qualityRatio;
const def = applyGrowthFormula(baseMonster.def, waveFactor, GrowthType.LINEAR) * typeMultiplier * qualityRatio;
return {
hp: Math.floor(hp),
mp: Math.floor(mp),
ap: Math.floor(ap),
def: Math.floor(def),
speed: Math.floor(speed)
};
}
/**
* 无限等级经验配置
*/
export function getLevelExp(level: number): number {
const baseExp = 100;
const growthFactor = 1.2;
return Math.floor(baseExp * Math.pow(growthFactor, level - 1));
}
/**
* 计算怪物掉落金币
*/
export function calculateMonsterGold(uuid: number, level: number, type: MonType): number {
const cost = MonsterCost[uuid] || 1;
let danger_ratio = 1 + cost * 0.1;
let type_ratio = 1;
if(type == MonType.BOSS) type_ratio = 10;
else if(type == MonType.ELITE) type_ratio = 3;
const baseGold = 10;
let gold = Math.floor((baseGold * type_ratio * danger_ratio + level) * 8);
return gold;
}
/**
* 计算怪物经验值
*/
export function calculateMonsterExp(uuid: number, level: number): number {
const cost = MonsterCost[uuid] || 1;
return Math.max(1, Math.floor(cost * 1.0 * Math.pow(1.15, level - 1) * 8));
}