feat(怪物生成): 添加全局配置系统并优化怪物生成逻辑
引入全局配置接口 IRogueGlobalConfig 用于集中管理怪物生成参数 添加配置获取和更新方法 getRogueConfig/updateRogueConfig 修改生成逻辑使用配置参数控制间隔、数量限制和预算计算 增加单次生成数量限制和同屏怪物数量限制
This commit is contained in:
@@ -6,7 +6,7 @@ import { MonStart } from "../common/config/heroSet";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
// 导入肉鸽配置
|
||||
import { getStageMonConfigs, MonType, generateMonstersFromBudget } from "./RogueConfig";
|
||||
import { getStageMonConfigs, MonType, generateMonstersFromBudget, getRogueConfig } from "./RogueConfig";
|
||||
import { BuffConf } from "../common/config/SkillSet";
|
||||
import { IndexSet, FacSet } from "../common/config/GameSet";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
@@ -64,30 +64,34 @@ export class MissionMonCompComp extends CCComp {
|
||||
|
||||
// 累加游戏时间
|
||||
this.gameTime += dt;
|
||||
const config = getRogueConfig();
|
||||
|
||||
// ==========================================
|
||||
// 新增:每秒执行一次刷怪逻辑 (Threat Budget)
|
||||
// ==========================================
|
||||
this.spawnLogicTimer += dt;
|
||||
if (this.spawnLogicTimer >= 1.0) {
|
||||
if (this.spawnLogicTimer >= config.spawnLogicInterval) {
|
||||
this.spawnLogicTimer = 0;
|
||||
|
||||
// 获取英雄血量比例
|
||||
const hpRatio = this.getHeroHpRatio();
|
||||
|
||||
// 生成怪物
|
||||
const newMonsters = generateMonstersFromBudget(this.gameTime, hpRatio);
|
||||
|
||||
// 添加到队列
|
||||
newMonsters.forEach(mon => {
|
||||
this.addToStageSpawnQueue(
|
||||
mon.uuid,
|
||||
mon.position !== undefined ? mon.position : 0,
|
||||
mon.type,
|
||||
mon.level,
|
||||
mon.buffs || []
|
||||
);
|
||||
});
|
||||
// 检查最大怪物数量限制
|
||||
if (smc.vmdata.mission_data.mon_num < config.maxMonsterCount) {
|
||||
// 获取英雄血量比例
|
||||
const hpRatio = this.getHeroHpRatio();
|
||||
|
||||
// 生成怪物
|
||||
const newMonsters = generateMonstersFromBudget(this.gameTime, hpRatio);
|
||||
|
||||
// 添加到队列
|
||||
newMonsters.forEach(mon => {
|
||||
this.addToStageSpawnQueue(
|
||||
mon.uuid,
|
||||
mon.position !== undefined ? mon.position : 0,
|
||||
mon.type,
|
||||
mon.level,
|
||||
mon.buffs || []
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 处理随机事件
|
||||
@@ -98,7 +102,7 @@ export class MissionMonCompComp extends CCComp {
|
||||
this.spawnTimer += dt;
|
||||
|
||||
// 正常召唤间隔
|
||||
if (this.spawnTimer >= this.spawnInterval) {
|
||||
if (this.spawnTimer >= config.spawnInterval) {
|
||||
this.spawnNextMonster();
|
||||
this.spawnTimer = 0;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
import { HeroInfo } from "../common/config/heroSet";
|
||||
|
||||
// 精英怪物配置表
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -241,28 +241,87 @@ function getSpawnWeights(timeInSeconds: number): SpawnWeight[] {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 全局刷怪配置接口
|
||||
*/
|
||||
export interface IRogueGlobalConfig {
|
||||
/** 场上最大怪物数量限制 */
|
||||
maxMonsterCount: number;
|
||||
/** 刷怪逻辑执行间隔(秒) - 决定多久计算一次生成 */
|
||||
spawnLogicInterval: number;
|
||||
/** 单个怪物生成间隔(秒) - 队列中怪物的实际生成频率 */
|
||||
spawnInterval: number;
|
||||
/** 基础威胁预算 - 每秒产生的基础点数 */
|
||||
baseBudget: number;
|
||||
/** 时间难度因子 - 每分钟增加的预算比例 (0.2 = 20%) */
|
||||
timeDifficultyFactor: number;
|
||||
/** 绝地求生阈值 - 英雄血量低于此比例时触发减缓刷怪 */
|
||||
survivalHpThreshold: number;
|
||||
/** 绝地求生预算乘数 - 触发阈值时的预算折扣 */
|
||||
survivalBudgetMultiplier: number;
|
||||
/** 单次逻辑最大生成怪物数限制 - 防止瞬间生成过多 */
|
||||
maxSpawnPerLogic: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认配置
|
||||
*/
|
||||
export const DefaultRogueConfig: IRogueGlobalConfig = {
|
||||
maxMonsterCount: 50, // 默认同屏50只
|
||||
spawnLogicInterval: 1.0, // 每秒计算一次
|
||||
spawnInterval: 0.6, // 队列出怪间隔0.6秒
|
||||
baseBudget: 1.5, // 基础预算
|
||||
timeDifficultyFactor: 0.2, // 每分钟增加20%预算
|
||||
survivalHpThreshold: 0.4, // 40%血量触发保护
|
||||
survivalBudgetMultiplier: 0.7, // 保护时预算打7折
|
||||
maxSpawnPerLogic: 10 // 单次最多生成10只
|
||||
};
|
||||
|
||||
// 当前配置实例
|
||||
let currentConfig: IRogueGlobalConfig = { ...DefaultRogueConfig };
|
||||
|
||||
/**
|
||||
* 获取当前全局配置
|
||||
*/
|
||||
export function getRogueConfig(): IRogueGlobalConfig {
|
||||
return currentConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新全局配置
|
||||
* @param config 部分或全部配置
|
||||
*/
|
||||
export function updateRogueConfig(config: Partial<IRogueGlobalConfig>) {
|
||||
currentConfig = {
|
||||
...currentConfig,
|
||||
...config
|
||||
};
|
||||
console.log("[RogueConfig] Configuration updated:", currentConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算当前威胁点数预算
|
||||
* @param timeInSeconds 游戏时间(秒)
|
||||
* @param heroHpRatio 英雄血量比例 (0-1)
|
||||
*/
|
||||
export function calculateBudget(timeInSeconds: number, heroHpRatio: number = 1.0): number {
|
||||
// 基础预算:每秒产生的点数
|
||||
// 假设1分钟时为20点,公式: Budget = Base * (1 + 60/60 * 0.2) = Base * 1.2 = 20 => Base ≈ 16
|
||||
// 修改:降低基础预算,避免队列积压。每秒 1.5 点左右(减半)。
|
||||
const Base_Budget = 1.5;
|
||||
const config = getRogueConfig();
|
||||
|
||||
// 基础预算
|
||||
const Base_Budget = config.baseBudget;
|
||||
|
||||
// 时间因子:随时间增加难度
|
||||
const timeFactor = 1 + (timeInSeconds / 60) * 0.2;
|
||||
const timeFactor = 1 + (timeInSeconds / 60) * config.timeDifficultyFactor;
|
||||
|
||||
// 强度乘数 (DDA):根据英雄状态调整
|
||||
let intensityMultiplier = 1.0;
|
||||
if (heroHpRatio < 0.4) {
|
||||
// 绝地求生:血量低于40%时,预算缩减30%
|
||||
intensityMultiplier = 0.7;
|
||||
if (heroHpRatio < config.survivalHpThreshold) {
|
||||
// 绝地求生:血量低于阈值时预算缩减
|
||||
intensityMultiplier = config.survivalBudgetMultiplier;
|
||||
}
|
||||
|
||||
// 公式: Budget(t) = Base_Budget * (1 + t/60 * 0.2) * Intensity_Multiplier
|
||||
// 公式: Budget(t) = Base_Budget * (1 + t/60 * Factor) * Intensity_Multiplier
|
||||
return Math.floor(Base_Budget * timeFactor * intensityMultiplier);
|
||||
}
|
||||
|
||||
@@ -272,17 +331,15 @@ export function calculateBudget(timeInSeconds: number, heroHpRatio: number = 1.0
|
||||
* @param heroHpRatio 英雄血量比例
|
||||
*/
|
||||
export function generateMonstersFromBudget(timeInSeconds: number, heroHpRatio: number = 1.0): IMonsConfig[] {
|
||||
// 15分钟后只生成Boss,且如果已经有Boss可能需要控制(这里简化为每次调用都尝试生成,由外部控制频率或唯一性)
|
||||
// 但根据"清除所有杂兵,锁定刷出最终BOSS",这里只返回Boss配置
|
||||
const config = getRogueConfig();
|
||||
|
||||
// 15分钟后只生成Boss
|
||||
if (timeInSeconds >= 15 * 60) {
|
||||
// 可以在这里做特殊处理,比如只返回一个Boss,或者返回空如果Boss已存在
|
||||
// 假设外部每秒调用,这里返回Boss,外部队列会堆积。
|
||||
// 建议:Boss波次由特殊逻辑控制,或者这里返回Boss但消耗巨大预算
|
||||
return [{
|
||||
uuid: 5701,
|
||||
type: MonType.BOSS,
|
||||
level: Math.floor(timeInSeconds / 60), // 等级随时间
|
||||
position: 2 // 中间位置
|
||||
level: Math.floor(timeInSeconds / 60),
|
||||
position: 2
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -300,29 +357,27 @@ export function generateMonstersFromBudget(timeInSeconds: number, heroHpRatio: n
|
||||
if (pool.length === 0) return [];
|
||||
|
||||
let attempts = 0;
|
||||
// 尝试消耗预算直到耗尽或无法购买最便宜的怪物
|
||||
const minCost = Math.min(...weights.map(w => MonsterCost[w.uuid] || 1));
|
||||
|
||||
while (currentBudget >= minCost && attempts < 50) {
|
||||
// 限制单次生成最大数量
|
||||
while (currentBudget >= minCost && attempts < 50 && monsters.length < config.maxSpawnPerLogic) {
|
||||
attempts++;
|
||||
|
||||
// 随机选择怪物
|
||||
const uuid = pool[Math.floor(Math.random() * pool.length)];
|
||||
const cost = MonsterCost[uuid] || 1;
|
||||
|
||||
if (currentBudget >= cost) {
|
||||
currentBudget -= cost;
|
||||
|
||||
// 确定怪物类型
|
||||
let type = MonType.NORMAL;
|
||||
if (uuid === 5701) type = MonType.BOSS; // 或者是精英,视情况而定
|
||||
if (uuid === 5701) type = MonType.BOSS;
|
||||
else if (MonsterCost[uuid] >= 10) type = MonType.ELITE;
|
||||
|
||||
monsters.push({
|
||||
uuid: uuid,
|
||||
type: type,
|
||||
level: Math.floor(timeInSeconds / 60) + 1, // 简单等级计算,实际属性由getMonAttr处理
|
||||
position: Math.floor(Math.random() * 5) // 随机位置 0-4
|
||||
level: Math.floor(timeInSeconds / 60) + 1,
|
||||
position: Math.floor(Math.random() * 5)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user