完成开箱抽卡 和 怪物掉落设置
This commit is contained in:
@@ -1,3 +1,222 @@
|
||||
// 掉落物品接口
|
||||
export interface DropItem {
|
||||
uuid: number; // 物品ID
|
||||
num: number; // 数量
|
||||
type: number; // 类型
|
||||
quality?: number; // 品质
|
||||
}
|
||||
|
||||
// 怪物类型
|
||||
export enum MonsterType {
|
||||
Normal = 1, // 普通怪
|
||||
Elite = 2, // 精英怪
|
||||
Boss = 3, // Boss怪
|
||||
}
|
||||
|
||||
// 掉落倍率配置
|
||||
export const DropRateConfig = {
|
||||
[MonsterType.Normal]: 1,
|
||||
[MonsterType.Elite]: 2,
|
||||
[MonsterType.Boss]: 10,
|
||||
}
|
||||
|
||||
// Boss掉落示例(最多5个不同英雄的碎片)
|
||||
// const bossDrops = getMonsterDrops(50, MonsterType.Boss, 1.2);
|
||||
|
||||
// 精英怪掉落示例(最多2个不同英雄的碎片)
|
||||
// const eliteDrops = getMonsterDrops(50, MonsterType.Elite, 1.2);
|
||||
|
||||
// 普通怪掉落示例(最多1个英雄的碎片)
|
||||
// const normalDrops = getMonsterDrops(50, MonsterType.Normal, 1.2);
|
||||
|
||||
/**
|
||||
* 获取怪物掉落
|
||||
* @param monsterLevel 怪物等级
|
||||
* @param monsterType 怪物类型
|
||||
* @param extraRate 额外倍率(比如玩家的幸运值加成)
|
||||
* @returns 掉落物品数组
|
||||
*/
|
||||
export function getMonsterDrops(
|
||||
monsterLevel: number,
|
||||
monsterType: MonsterType = MonsterType.Normal,
|
||||
extraRate: number = 1
|
||||
): DropItem[] {
|
||||
const drops: DropItem[] = [];
|
||||
const baseMultiplier = getDropMultiplier(monsterLevel);
|
||||
const monsterMultiplier = DropRateConfig[monsterType];
|
||||
const totalMultiplier = baseMultiplier * monsterMultiplier * extraRate;
|
||||
|
||||
// 分离英雄碎片和道具配置
|
||||
const heroChipConfigs = DropConfigList.filter(config => config.type === dorptype.hero_chip);
|
||||
const itemConfigs = DropConfigList.filter(config => config.type === dorptype.items);
|
||||
|
||||
// 获取当前怪物类型可以掉落的英雄碎片数量
|
||||
const maxHeroChips = HeroChipDropCount[monsterType];
|
||||
|
||||
// 随机选择指定数量的英雄碎片
|
||||
const selectedHeroChips = shuffleArray(heroChipConfigs).slice(0, maxHeroChips);
|
||||
|
||||
// 处理英雄碎片掉落
|
||||
for (const config of selectedHeroChips) {
|
||||
if (monsterType === MonsterType.Normal) {
|
||||
// 普通怪按概率掉落
|
||||
if (shouldDrop(config.dropRate * totalMultiplier)) {
|
||||
const dropItem = calculateDrop(config, monsterLevel, monsterType);
|
||||
if (dropItem) {
|
||||
drops.push(dropItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 精英怪和Boss必定掉落
|
||||
const dropItem = calculateDrop(config, monsterLevel, monsterType);
|
||||
if (dropItem) {
|
||||
drops.push(dropItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理道具掉落
|
||||
for (const config of itemConfigs) {
|
||||
if (config.uuid === 9001) {
|
||||
// 金币必定掉落
|
||||
const dropItem = calculateDrop(config, monsterLevel, monsterType);
|
||||
if (dropItem) {
|
||||
drops.push(dropItem);
|
||||
}
|
||||
} else {
|
||||
// 其他道具按概率掉落
|
||||
if (shouldDrop(config.dropRate * totalMultiplier)) {
|
||||
const dropItem = calculateDrop(config, monsterLevel, monsterType);
|
||||
if (dropItem) {
|
||||
drops.push(dropItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drops;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算是否掉落
|
||||
* @param rate 掉落概率
|
||||
*/
|
||||
function shouldDrop(rate: number): boolean {
|
||||
return Math.random() * 100 <= Math.min(rate, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算单个物品掉落
|
||||
*/
|
||||
function calculateDrop(
|
||||
config: typeof DropConfigList[0],
|
||||
monsterLevel: number,
|
||||
monsterType: MonsterType
|
||||
): DropItem | null {
|
||||
// 计算掉落数量
|
||||
let num = Math.floor(Math.random() * config.num_max) + 1;
|
||||
|
||||
// Boss额外保底
|
||||
if (monsterType === MonsterType.Boss && num < config.num_max * 0.3) {
|
||||
num = Math.floor(config.num_max * 0.3);
|
||||
}
|
||||
|
||||
// 根据类型应用不同规则
|
||||
if (config.type === dorptype.hero_chip) {
|
||||
// 英雄碎片特殊处理
|
||||
return {
|
||||
uuid: config.uuid,
|
||||
num: Math.min(num, 10), // 英雄碎片单次最多10个
|
||||
type: config.type,
|
||||
quality: getHeroQuality(config.uuid)
|
||||
};
|
||||
} else if (config.type === dorptype.items) {
|
||||
// 普通道具处理
|
||||
return {
|
||||
uuid: config.uuid,
|
||||
num: num,
|
||||
type: config.type
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取英雄品质(需要和heroSet配置关联)
|
||||
*/
|
||||
function getHeroQuality(heroId: number): number {
|
||||
// 这里可以从heroSet中获取英雄品质
|
||||
return 1; // 默认品质
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取掉落倍率
|
||||
* @param monsterLevel 怪物等级
|
||||
*/
|
||||
export function getDropMultiplier(monsterLevel: number): number {
|
||||
// 基础倍率
|
||||
let multiplier = Math.max(1, Math.floor(monsterLevel / 10));
|
||||
|
||||
// 等级档位加成
|
||||
if (monsterLevel >= 50) multiplier *= 1.5;
|
||||
if (monsterLevel >= 100) multiplier *= 2;
|
||||
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成掉落
|
||||
* @param times 掉落次数
|
||||
* @param params 掉落参数
|
||||
*/
|
||||
export function batchGenerateDrops(
|
||||
times: number,
|
||||
monsterLevel: number,
|
||||
monsterType: MonsterType = MonsterType.Normal,
|
||||
extraRate: number = 1
|
||||
): DropItem[] {
|
||||
const allDrops: DropItem[] = [];
|
||||
|
||||
for (let i = 0; i < times; i++) {
|
||||
const drops = getMonsterDrops(monsterLevel, monsterType, extraRate);
|
||||
allDrops.push(...drops);
|
||||
}
|
||||
|
||||
// 合并相同物品
|
||||
return mergeDrops(allDrops);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并相同物品的掉落
|
||||
*/
|
||||
function mergeDrops(drops: DropItem[]): DropItem[] {
|
||||
const mergedMap = new Map<string, DropItem>();
|
||||
|
||||
drops.forEach(drop => {
|
||||
const key = `${drop.uuid}-${drop.type}`;
|
||||
if (mergedMap.has(key)) {
|
||||
const existing = mergedMap.get(key)!;
|
||||
existing.num += drop.num;
|
||||
} else {
|
||||
mergedMap.set(key, {...drop});
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(mergedMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机打乱数组
|
||||
*/
|
||||
function shuffleArray<T>(array: T[]): T[] {
|
||||
const newArray = [...array];
|
||||
for (let i = newArray.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
export const BoxDrop={
|
||||
1:[
|
||||
@@ -5,14 +224,62 @@ export const BoxDrop={
|
||||
{uuid: 9003,dropRate: 10,num_max: 500,type:0},
|
||||
],
|
||||
2:[
|
||||
{uuid: 5001,dropRate: 10,num_max: 10,type:0},
|
||||
{uuid: 5002,dropRate: 10,num_max: 10,type:0},
|
||||
{uuid: 5003,dropRate: 50,num_max: 10,type:0},
|
||||
{uuid: 5001,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5002,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5003,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5004,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5005,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5006,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5007,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5008,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5009,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5010,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5011,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5012,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5013,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5014,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5015,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5016,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5017,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5018,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5019,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5020,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5021,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5022,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5023,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5024,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5025,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5026,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5027,dropRate: 100/7,num_max: 5,type:1},
|
||||
],
|
||||
3:[
|
||||
{uuid: 5001,dropRate: 20,num_max: 10,type:0},
|
||||
{uuid: 5002,dropRate: 20,num_max: 10,type:0},
|
||||
{uuid: 5003,dropRate: 50,num_max: 10,type:0},
|
||||
{uuid: 5001,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5002,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5003,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5004,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5005,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5006,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5007,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5008,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5009,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5010,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5011,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5012,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5013,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5014,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5015,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5016,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5017,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5018,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5019,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5020,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5021,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5022,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5023,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5024,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5025,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5026,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5027,dropRate: 100/7,num_max: 5,type:1},
|
||||
],
|
||||
}
|
||||
export const BoxDropCount={
|
||||
@@ -20,4 +287,66 @@ export const BoxDropCount={
|
||||
2:3,
|
||||
3:3,
|
||||
}
|
||||
export const dorptype={
|
||||
hero_chip:1,
|
||||
items:2,
|
||||
}
|
||||
export const HeroChipDropCount={
|
||||
1:1,
|
||||
2:2,
|
||||
3:5,
|
||||
}
|
||||
//HeroChipList = [5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027]
|
||||
//ItemsList=[9001,1003]
|
||||
//根据HeroChipList,ItemsList设置掉落概率
|
||||
export const DropConfigList=[
|
||||
{uuid: 5001,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5002,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5003,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5004,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5005,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5006,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5007,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5008,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5009,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5010,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5011,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5012,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5013,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5014,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5015,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5016,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5017,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5018,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5019,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5020,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5021,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5022,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5023,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5024,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5025,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5026,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 5027,dropRate: 100/7,num_max: 5,type:1},
|
||||
{uuid: 9001,dropRate: 100,num_max: 1000,type:2},
|
||||
{uuid: 1003,dropRate: 20,num_max: 1,type:2},
|
||||
]
|
||||
|
||||
// 使用示例:
|
||||
/*
|
||||
// 单次掉落
|
||||
const drops = getMonsterDrops(50, MonsterType.Boss, 1.2);
|
||||
|
||||
// 批量掉落(比如连续击杀多个怪物)
|
||||
const batchDrops = batchGenerateDrops(5, 50, MonsterType.Elite, 1.2);
|
||||
|
||||
// 处理掉落物品
|
||||
drops.forEach(item => {
|
||||
if (item.type === dorptype.hero_chip) {
|
||||
// 处理英雄碎片
|
||||
console.log(`获得英雄碎片: ${item.uuid} x${item.num}`);
|
||||
} else if (item.type === dorptype.items) {
|
||||
// 处理道具
|
||||
console.log(`获得道具: ${item.uuid} x${item.num}`);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user