368 lines
18 KiB
TypeScript
368 lines
18 KiB
TypeScript
import * as exp from "constants";
|
||
import { QualitySet } from "./BoxSet";
|
||
|
||
export enum ItemType{
|
||
NORMAL=0,//普通
|
||
SPECIAL=1,//特殊 可双击打开
|
||
EQUIP=2,//装备
|
||
}
|
||
|
||
// 掉落物品接口
|
||
export interface DropItem {
|
||
item_uuid: number; // 物品ID
|
||
probability: number; // 掉落概率 (0-1之间)
|
||
minCount: number; // 最小掉落数量
|
||
maxCount: number; // 最大掉落数量
|
||
baseCount: number; // 基础掉落数量
|
||
growthRate: number; // 增长参数
|
||
}
|
||
|
||
// 怪物掉落配置接口
|
||
export interface MonsterDropConfig {
|
||
monsterId: number; // 怪物ID
|
||
quality: QualitySet; // 怪物品质
|
||
drops: DropItem[]; // 掉落物品列表
|
||
}
|
||
|
||
export const Items={
|
||
1001:{uuid: 1001,path: "1001",type:1,quality:QualitySet.GREEN,name: "绿色英雄石",info:"稀有英雄升星必须材料", },
|
||
1002:{uuid: 1002,path: "1002",type:1,quality:QualitySet.BLUE,name: "蓝色英雄石",info:"史诗英雄升星必须材料", },
|
||
1003:{uuid: 1003,path: "1003",type:1,quality:QualitySet.PURPLE,name: "紫色英雄石",info:"传说英雄升星必须材料", },
|
||
1004:{uuid: 1004,path: "1004",type:1,quality:QualitySet.ORANGE,name: "红色英雄石",info:"传说英雄升星必须材料", },
|
||
1005:{uuid: 1005,path: "1005",type:1,quality:QualitySet.ORANGE,name: "招募劵",info:"可以在英雄酒馆招募英雄", },
|
||
1006:{uuid: 1006,path: "1006",type:1,quality:QualitySet.BLUE,name: "铜钥匙",info:"解锁稀有英雄 也可以直接兑换金币", },
|
||
1007:{uuid: 1007,path: "1007",type:1,quality:QualitySet.PURPLE,name: "银钥匙",info:"解锁史诗英雄 也可以直接兑换金币", },
|
||
1008:{uuid: 1008,path: "1008",type:1,quality:QualitySet.ORANGE,name: "金钥匙",info:"解锁传说英雄 也可以直接兑换金币", },
|
||
}
|
||
|
||
export enum DropKey{
|
||
ItemUUId=0, // 物品ID
|
||
Pro=1, // 概率
|
||
Diff=2, // 上下限差值
|
||
Base=3, // 基础数量
|
||
GrowthRate=4, // 增长参数
|
||
}
|
||
|
||
// 怪物掉落配置表 - 按照DropKey顺序配置
|
||
export const MonsterDropTable: { [monsterId: number]: [number, number, number, number, number][] } = {
|
||
// 普通怪物 - 绿色品质
|
||
5201: [ // 兽人战士
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.3, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 30%概率掉落铜钥匙
|
||
],
|
||
5202: [ // 兽人刺客
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.4, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 40%概率掉落铜钥匙
|
||
],
|
||
5203: [ // 兽人护卫
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.3, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 30%概率掉落铜钥匙
|
||
],
|
||
5204: [ // 石卫
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.35, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 35%概率掉落铜钥匙
|
||
],
|
||
5205: [ // 土卫
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.35, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 35%概率掉落铜钥匙
|
||
],
|
||
5206: [ // 树卫
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.35, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 35%概率掉落铜钥匙
|
||
],
|
||
5219: [ // 牛头战士
|
||
[Items[1001].uuid, 1.0, 1, 1, 0.25], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1-2个绿色英雄石
|
||
[Items[1006].uuid, 0.4, 0, 1, 0.15] // [item_uuid, probability, diff, baseCount, growthRate] - 40%概率掉落铜钥匙
|
||
],
|
||
5220: [ // 牛头战士
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.3, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 30%概率掉落铜钥匙
|
||
],
|
||
5221: [ // 牛头战士
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.4, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 40%概率掉落铜钥匙
|
||
],
|
||
5222: [ // 独眼巨人
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.3, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 30%概率掉落铜钥匙
|
||
],
|
||
5223: [ // 独眼巨人
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.3, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 30%概率掉落铜钥匙
|
||
],
|
||
5224: [ // 独眼巨人
|
||
[Items[1001].uuid, 1.0, 0, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个绿色英雄石
|
||
[Items[1006].uuid, 0.4, 0, 1, 0.1] // [item_uuid, probability, diff, baseCount, growthRate] - 40%概率掉落铜钥匙
|
||
],
|
||
|
||
// 精英怪物 - 蓝色品质
|
||
5225: [ // 精英独眼
|
||
[Items[1001].uuid, 1.0, 1, 2, 0.3], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落2-3个绿色英雄石
|
||
[Items[1002].uuid, 1.0, 0, 1, 0.25], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个蓝色英雄石
|
||
[Items[1006].uuid, 0.6, 1, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 60%概率掉落铜钥匙
|
||
[Items[1007].uuid, 0.2, 0, 1, 0.15] // [item_uuid, probability, diff, baseCount, growthRate] - 20%概率掉落银钥匙
|
||
],
|
||
5226: [ // 精英牛头
|
||
[Items[1001].uuid, 1.0, 1, 2, 0.3], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落2-3个绿色英雄石
|
||
[Items[1002].uuid, 1.0, 0, 1, 0.25], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个蓝色英雄石
|
||
[Items[1006].uuid, 0.6, 1, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 60%概率掉落铜钥匙
|
||
[Items[1007].uuid, 0.2, 0, 1, 0.15] // [item_uuid, probability, diff, baseCount, growthRate] - 20%概率掉落银钥匙
|
||
],
|
||
5227: [ // 精英兽人
|
||
[Items[1001].uuid, 1.0, 1, 2, 0.3], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落2-3个绿色英雄石
|
||
[Items[1002].uuid, 1.0, 0, 1, 0.25], // [item_uuid, probability, diff, baseCount, growthRate] - 100%掉落1个蓝色英雄石
|
||
[Items[1006].uuid, 0.6, 1, 1, 0.2], // [item_uuid, probability, diff, baseCount, growthRate] - 60%概率掉落铜钥匙
|
||
[Items[1007].uuid, 0.2, 0, 1, 0.15] // [item_uuid, probability, diff, baseCount, growthRate] - 20%概率掉落银钥匙
|
||
]
|
||
};
|
||
|
||
// 基础资源掉落配置表 - 以普通怪为基础值
|
||
export const BaseResourceDropConfig = {
|
||
// 经验值配置
|
||
exp: {
|
||
baseValue: 100, // 普通怪基础经验值
|
||
stageMultiplier: 1.15, // 关卡倍数 (降低增长)
|
||
randomRange: 0.2, // 随机范围 (±20%)
|
||
baseProbability: 1.0 // 基础掉落概率 (100%)
|
||
},
|
||
// 金币配置
|
||
gold: {
|
||
baseValue: 50, // 普通怪基础金币值
|
||
stageMultiplier: 1.12, // 关卡倍数 (降低增长)
|
||
randomRange: 0.25, // 随机范围 (±25%)
|
||
baseProbability: 0.7 // 基础掉落概率 (70%)
|
||
},
|
||
// 钻石配置
|
||
diamond: {
|
||
baseValue: 2, // 基础钻石值
|
||
stageMultiplier: 1.05, // 关卡倍数 (大幅降低增长)
|
||
randomRange: 0.2, // 随机范围 (±20%)
|
||
baseProbability: 0.0 // 基础掉落概率 (0%,需要品质加成)
|
||
}
|
||
};
|
||
|
||
// 怪物品质加成配置表 - 使用加法权重
|
||
export const QualityBonusConfig = {
|
||
[QualitySet.GREEN]: {
|
||
// 绿色品质:基础值 + 加成
|
||
expBonus: 0, // 经验值加成
|
||
goldBonus: 0, // 金币加成
|
||
diamondBonus: 0, // 钻石加成
|
||
expProbabilityBonus: 0, // 经验掉落概率加成
|
||
goldProbabilityBonus: 0, // 金币掉落概率加成
|
||
diamondProbabilityBonus: 0 // 钻石掉落概率加成
|
||
},
|
||
[QualitySet.BLUE]: {
|
||
// 蓝色品质:基础值 + 加成
|
||
expBonus: 50, // 经验值 +50
|
||
goldBonus: 25, // 金币 +25
|
||
diamondBonus: 0, // 钻石加成 0
|
||
expProbabilityBonus: 0, // 经验掉落概率加成
|
||
goldProbabilityBonus: 0.1, // 金币掉落概率 +10%
|
||
diamondProbabilityBonus: 0.2 // 钻石掉落概率 +20%
|
||
},
|
||
[QualitySet.PURPLE]: {
|
||
// 紫色品质:基础值 + 加成
|
||
expBonus: 100, // 经验值 +100
|
||
goldBonus: 50, // 金币 +50
|
||
diamondBonus: 1, // 钻石 +1
|
||
expProbabilityBonus: 0, // 经验掉落概率加成
|
||
goldProbabilityBonus: 0.2, // 金币掉落概率 +20%
|
||
diamondProbabilityBonus: 0.1 // 钻石掉落概率 +10%(精英10%)
|
||
},
|
||
[QualitySet.ORANGE]: {
|
||
// 橙色品质:基础值 + 加成
|
||
expBonus: 200, // 经验值 +200
|
||
goldBonus: 100, // 金币 +100
|
||
diamondBonus: 3, // 钻石 +3
|
||
expProbabilityBonus: 0, // 经验掉落概率加成
|
||
goldProbabilityBonus: 0.3, // 金币掉落概率 +30%
|
||
diamondProbabilityBonus: 1.0 // 钻石掉落概率 +100%(BOSS必掉)
|
||
}
|
||
};
|
||
|
||
// 关卡和buff加成配置表 - 使用加法权重
|
||
export const StageBuffBonusConfig = {
|
||
// 关卡加成配置
|
||
stage: {
|
||
expBonusPerStage: 5, // 每关经验值加成
|
||
goldBonusPerStage: 2, // 每关金币加成
|
||
diamondBonusPerStage: 0.1, // 每关钻石加成
|
||
expProbabilityBonusPerStage: 0, // 每关经验掉落概率加成
|
||
goldProbabilityBonusPerStage: 0, // 每关金币掉落概率加成
|
||
diamondProbabilityBonusPerStage: 0 // 每关钻石掉落概率加成
|
||
},
|
||
// buff数量加成配置
|
||
buff: {
|
||
expBonusPerBuff: 10, // 每个buff经验值加成
|
||
goldBonusPerBuff: 5, // 每个buff金币加成
|
||
diamondBonusPerBuff: 0.5, // 每个buff钻石加成
|
||
expProbabilityBonusPerBuff: 0, // 每个buff经验掉落概率加成
|
||
goldProbabilityBonusPerBuff: 0.01, // 每个buff金币掉落概率加成
|
||
diamondProbabilityBonusPerBuff: 0.005 // 每个buff钻石掉落概率加成
|
||
}
|
||
};
|
||
|
||
// 怪物掉落管理器
|
||
export class MonsterDropManager {
|
||
|
||
/**
|
||
* 根据怪物ID获取掉落配置
|
||
* @param monsterId 怪物ID
|
||
* @returns 掉落配置
|
||
*/
|
||
static getDropConfig(monsterId: number): [number, number, number, number, number][] | null {
|
||
return MonsterDropTable[monsterId] || null;
|
||
}
|
||
|
||
/**
|
||
* 计算指定关卡数的掉落数量
|
||
* @param baseCount 基础数量
|
||
* @param growthRate 增长参数
|
||
* @param stageNumber 关卡数
|
||
* @param diff 上下限差值
|
||
* @returns 计算后的掉落数量
|
||
*/
|
||
static calculateDropCount(baseCount: number, growthRate: number, stageNumber: number, diff: number): number {
|
||
// 公式:基础数量 * 增长参数 * 关卡数 + (0-差值的随机数)
|
||
const calculatedCount = baseCount * growthRate * stageNumber;
|
||
const randomBonus = Math.floor(Math.random() * (diff + 1)); // 0到diff的随机数
|
||
const finalCount = calculatedCount + randomBonus;
|
||
|
||
// 允许掉落数量为0
|
||
return Math.max(0, Math.floor(finalCount));
|
||
}
|
||
|
||
/**
|
||
* 计算怪物掉落物品
|
||
* @param monsterId 怪物ID
|
||
* @param stageNumber 关卡数
|
||
* @param playerLuck 玩家幸运值加成
|
||
* @returns 掉落物品数组
|
||
*/
|
||
static calculateMonsterDrops(monsterId: number, stageNumber: number, playerLuck: number = 0): Array<{item_uuid: number, count: number}> {
|
||
const dropArray = this.getDropConfig(monsterId);
|
||
if (!dropArray) {
|
||
console.warn(`[MonsterDropManager]: No drop config found for monster ${monsterId}`);
|
||
return [];
|
||
}
|
||
|
||
const result: Array<{item_uuid: number, count: number}> = [];
|
||
const luckBonus = 1 + (playerLuck * 0.01); // 幸运值加成
|
||
|
||
// 处理所有掉落物品(统一按概率处理)
|
||
dropArray.forEach(dropData => {
|
||
const [item_uuid, probability, diff, baseCount, growthRate] = dropData;
|
||
|
||
if (Math.random() < probability) {
|
||
// 使用新的计算公式:基础值*关卡数*增长参数+(0-差值的随机数)
|
||
const finalCount = this.calculateDropCount(baseCount, growthRate, stageNumber, diff);
|
||
const countWithLuck = Math.floor(finalCount * luckBonus);
|
||
|
||
result.push({
|
||
item_uuid: item_uuid,
|
||
count: Math.max(1, countWithLuck) // 确保至少掉落1个
|
||
});
|
||
}
|
||
});
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 预览指定关卡数的掉落数量(不包含随机因素)
|
||
* @param monsterId 怪物ID
|
||
* @param stageNumber 关卡数
|
||
* @returns 掉落物品预览数组
|
||
*/
|
||
static previewMonsterDrops(monsterId: number, stageNumber: number): Array<{item_uuid: number, baseCount: number, calculatedCount: number, maxCount: number}> {
|
||
const dropArray = this.getDropConfig(monsterId);
|
||
if (!dropArray) {
|
||
console.warn(`[MonsterDropManager]: No drop config found for monster ${monsterId}`);
|
||
return [];
|
||
}
|
||
|
||
const result: Array<{item_uuid: number, baseCount: number, calculatedCount: number, maxCount: number}> = [];
|
||
|
||
// 处理所有掉落物品
|
||
dropArray.forEach(dropData => {
|
||
const [item_uuid, probability, diff, baseCount, growthRate] = dropData;
|
||
const calculatedCount = baseCount * growthRate * stageNumber;
|
||
const maxCount = calculatedCount + diff;
|
||
|
||
result.push({
|
||
item_uuid: item_uuid,
|
||
baseCount: baseCount,
|
||
calculatedCount: Math.floor(calculatedCount),
|
||
maxCount: Math.floor(maxCount)
|
||
});
|
||
});
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 计算怪物基础资源掉落(经验、金币、钻石)
|
||
* @param monsterQuality 怪物品质
|
||
* @param stageNumber 关卡数
|
||
* @param buffCount buff数量
|
||
* @returns 基础资源掉落结果
|
||
*/
|
||
static calculateBaseResourceDrops(monsterQuality: QualitySet, stageNumber: number, buffCount: number = 0): {exp: number, gold?: number, diamond?: number} {
|
||
const result: {exp: number, gold?: number, diamond?: number} = {exp: 0};
|
||
|
||
// 获取品质加成
|
||
const qualityBonus = QualityBonusConfig[monsterQuality];
|
||
|
||
// 计算经验值(必出)
|
||
const expConfig = BaseResourceDropConfig.exp;
|
||
const expValue = (expConfig.baseValue +
|
||
qualityBonus.expBonus +
|
||
StageBuffBonusConfig.stage.expBonusPerStage * stageNumber +
|
||
StageBuffBonusConfig.buff.expBonusPerBuff * buffCount) *
|
||
Math.pow(expConfig.stageMultiplier, stageNumber - 1);
|
||
|
||
// 添加随机范围
|
||
const expRandomFactor = 1 + (Math.random() - 0.5) * 2 * expConfig.randomRange;
|
||
result.exp = Math.floor(expValue * expRandomFactor);
|
||
|
||
// 金币与钻石独立判定,可同时掉落:
|
||
// 使用加法权重系统:基础值 + 品质加成 + 关卡加成 + buff加成 + 关卡增长
|
||
|
||
// 金币判定
|
||
const goldProbability = BaseResourceDropConfig.gold.baseProbability +
|
||
qualityBonus.goldProbabilityBonus +
|
||
StageBuffBonusConfig.stage.goldProbabilityBonusPerStage * stageNumber +
|
||
StageBuffBonusConfig.buff.goldProbabilityBonusPerBuff * buffCount;
|
||
if (Math.random() < goldProbability) {
|
||
const goldConfig = BaseResourceDropConfig.gold;
|
||
const goldValue = (goldConfig.baseValue +
|
||
qualityBonus.goldBonus +
|
||
StageBuffBonusConfig.stage.goldBonusPerStage * stageNumber +
|
||
StageBuffBonusConfig.buff.goldBonusPerBuff * buffCount) *
|
||
Math.pow(goldConfig.stageMultiplier, stageNumber - 1);
|
||
const goldRandomFactor = 1 + (Math.random() - 0.5) * 2 * goldConfig.randomRange;
|
||
result.gold = Math.floor(goldValue * goldRandomFactor);
|
||
}
|
||
|
||
// 钻石判定
|
||
const diamondProbability = BaseResourceDropConfig.diamond.baseProbability +
|
||
qualityBonus.diamondProbabilityBonus +
|
||
StageBuffBonusConfig.stage.diamondProbabilityBonusPerStage * stageNumber +
|
||
StageBuffBonusConfig.buff.diamondProbabilityBonusPerBuff * buffCount;
|
||
if (Math.random() < diamondProbability) {
|
||
const diamondConfig = BaseResourceDropConfig.diamond;
|
||
const diamondValue = (diamondConfig.baseValue +
|
||
qualityBonus.diamondBonus +
|
||
StageBuffBonusConfig.stage.diamondBonusPerStage * stageNumber +
|
||
StageBuffBonusConfig.buff.diamondBonusPerBuff * buffCount) *
|
||
Math.pow(diamondConfig.stageMultiplier, stageNumber - 1);
|
||
const diamondRandomFactor = 1 + (Math.random() - 0.5) * 2 * diamondConfig.randomRange;
|
||
result.diamond = Math.floor(diamondValue * diamondRandomFactor);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|
||
|