refactor(CardSet): 重构默认卡池获取逻辑,支持动态权重计算
重构 getDefaultPool 函数,将重复逻辑统一处理并支持基于解锁等级的动态权重计算。新实现: 1. 统一处理所有卡牌类型的配置映射 2. 自动累加所有小于等于当前等级的配置项 3. 根据解锁等级动态计算权重,高等级卡牌出现概率更高 4. 保留原有兜底逻辑作为最后防线
This commit is contained in:
@@ -138,77 +138,110 @@ function getCardBaseInfo(type: CardType, uuid: number): ICardInfo | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取默认的全量池 (当配置未指定items时使用)
|
* 获取指定类型的全量池
|
||||||
|
* 自动累加所有 <= level 的配置项
|
||||||
* @param type 卡牌类型
|
* @param type 卡牌类型
|
||||||
* @param level 当前等级(可选,用于从各模块的CanSelect配置中获取)
|
* @param level 当前等级
|
||||||
*/
|
*/
|
||||||
function getDefaultPool(type: CardType, level: number = 1): IPoolItem[] {
|
function getDefaultPool(type: CardType, level: number = 1): IPoolItem[] {
|
||||||
const items: IPoolItem[] = [];
|
const items: IPoolItem[] = [];
|
||||||
|
let configMap: Record<number, number[]> | null = null;
|
||||||
|
let defaultWeight = 100;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CardType.Attr:
|
case CardType.Attr:
|
||||||
// 优先使用 CanSelectAttrs 中的配置
|
configMap = CanSelectAttrs;
|
||||||
if (CanSelectAttrs[level]) {
|
defaultWeight = 100;
|
||||||
CanSelectAttrs[level].forEach(id => items.push({ id, weight: 100 }));
|
|
||||||
} else if (CanSelectAttrs[99]) {
|
|
||||||
// 默认池
|
|
||||||
CanSelectAttrs[99].forEach(id => items.push({ id, weight: 100 }));
|
|
||||||
} else {
|
|
||||||
// 全量兜底
|
|
||||||
Object.keys(AttrCards).forEach(key => items.push({ id: Number(key), weight: 100 }));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CardType.Talent:
|
case CardType.Talent:
|
||||||
// 优先使用 CanSelectTalents 中的配置
|
configMap = CanSelectTalents;
|
||||||
if (CanSelectTalents[level]) {
|
defaultWeight = 50;
|
||||||
CanSelectTalents[level].forEach(id => items.push({ id, weight: 50 }));
|
|
||||||
} else if (CanSelectTalents[99]) {
|
|
||||||
// 默认池
|
|
||||||
CanSelectTalents[99].forEach(id => items.push({ id, weight: 50 }));
|
|
||||||
} else {
|
|
||||||
// 全量兜底
|
|
||||||
Object.keys(talConf).forEach(key => items.push({ id: Number(key), weight: 50 }));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CardType.Skill:
|
case CardType.Skill:
|
||||||
// 优先使用 CanSelectSkills 中的配置
|
configMap = CanSelectSkills;
|
||||||
if (CanSelectSkills[level]) {
|
defaultWeight = 80;
|
||||||
CanSelectSkills[level].forEach(id => items.push({ id, weight: 80 }));
|
|
||||||
} else if (CanSelectSkills[99]) {
|
|
||||||
// 默认池
|
|
||||||
CanSelectSkills[99].forEach(id => items.push({ id, weight: 80 }));
|
|
||||||
} else {
|
|
||||||
// 全量兜底
|
|
||||||
Object.keys(SkillSet).forEach(key => items.push({ id: Number(key), weight: 80 }));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CardType.Partner:
|
case CardType.Partner:
|
||||||
// 优先使用 CanSelectHeros 中的配置
|
configMap = CanSelectHeros;
|
||||||
if (CanSelectHeros[level]) {
|
defaultWeight = 100;
|
||||||
CanSelectHeros[level].forEach(id => items.push({ id, weight: 100 }));
|
break;
|
||||||
} else if (CanSelectHeros[99]) {
|
case CardType.Potion:
|
||||||
// 默认池
|
configMap = CanSelectPotions;
|
||||||
CanSelectHeros[99].forEach(id => items.push({ id, weight: 100 }));
|
defaultWeight = 100;
|
||||||
} else {
|
break;
|
||||||
// 全量兜底 (排除怪物)
|
}
|
||||||
|
|
||||||
|
if (configMap) {
|
||||||
|
// 收集所有已解锁的ID (去重)
|
||||||
|
const unlockedIds = new Set<number>();
|
||||||
|
|
||||||
|
// 1. 遍历所有等级配置,收集 <= level 的项
|
||||||
|
Object.keys(configMap).forEach(lvlStr => {
|
||||||
|
const lv = parseInt(lvlStr);
|
||||||
|
// 忽略 99 (默认全开) 这种特殊标记,只处理正常等级逻辑
|
||||||
|
if (lv <= level && lv !== 99) {
|
||||||
|
const ids = configMap![lv];
|
||||||
|
if (ids) {
|
||||||
|
// 计算权重:等级越高,权重越高
|
||||||
|
// 基础权重 defaultWeight
|
||||||
|
// 额外权重:(解锁等级 / 当前等级) * 基础权重 * 2
|
||||||
|
// 例如:当前10级
|
||||||
|
// 1级卡权重: 100 + (1/10)*200 = 120
|
||||||
|
// 9级卡权重: 100 + (9/10)*200 = 280
|
||||||
|
// 这样新解锁的卡牌出现概率显著高于旧卡牌
|
||||||
|
const extraWeight = Math.floor((lv / Math.max(1, level)) * defaultWeight * 2);
|
||||||
|
const finalWeight = defaultWeight + extraWeight;
|
||||||
|
|
||||||
|
ids.forEach(id => {
|
||||||
|
// 如果已经存在(可能在低等级也配置了),取最大权重
|
||||||
|
const existing = items.find(i => i.id === id);
|
||||||
|
if (existing) {
|
||||||
|
existing.weight = Math.max(existing.weight, finalWeight);
|
||||||
|
} else {
|
||||||
|
items.push({ id, weight: finalWeight });
|
||||||
|
}
|
||||||
|
unlockedIds.add(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 如果当前等级没有任何解锁项,且存在 99 号默认配置,则回退使用 99 号配置
|
||||||
|
// 这种行为保持了原有逻辑的"兜底"特性,但更智能
|
||||||
|
if (unlockedIds.size === 0 && configMap[99]) {
|
||||||
|
configMap[99].forEach(id => {
|
||||||
|
items.push({ id, weight: defaultWeight });
|
||||||
|
unlockedIds.add(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 构建结果 (items 已经在循环中构建好了,这里不需要再从 unlockedIds 重新构建)
|
||||||
|
// unlockedIds.forEach(id => items.push({ id, weight: defaultWeight }));
|
||||||
|
} else {
|
||||||
|
// 兜底逻辑:如果该类型没有配置表 (理论上不应发生,除非新增类型未配置)
|
||||||
|
// 这里保留原有的全量兜底逻辑作为最后的防线
|
||||||
|
switch (type) {
|
||||||
|
case CardType.Attr:
|
||||||
|
Object.keys(AttrCards).forEach(key => items.push({ id: Number(key), weight: 100 }));
|
||||||
|
break;
|
||||||
|
case CardType.Talent:
|
||||||
|
Object.keys(talConf).forEach(key => items.push({ id: Number(key), weight: 50 }));
|
||||||
|
break;
|
||||||
|
case CardType.Skill:
|
||||||
|
Object.keys(SkillSet).forEach(key => items.push({ id: Number(key), weight: 80 }));
|
||||||
|
break;
|
||||||
|
case CardType.Partner:
|
||||||
Object.keys(HeroInfo).forEach(key => {
|
Object.keys(HeroInfo).forEach(key => {
|
||||||
const id = Number(key);
|
const id = Number(key);
|
||||||
if (id < 5200) items.push({ id, weight: 100 });
|
if (id < 5200) items.push({ id, weight: 100 });
|
||||||
});
|
});
|
||||||
}
|
break;
|
||||||
break;
|
case CardType.Potion:
|
||||||
case CardType.Potion:
|
|
||||||
// 优先使用 CanSelectPotions 中的配置
|
|
||||||
if (CanSelectPotions[level]) {
|
|
||||||
CanSelectPotions[level].forEach(id => items.push({ id, weight: 100 }));
|
|
||||||
} else if (CanSelectPotions[99]) {
|
|
||||||
// 默认池
|
|
||||||
CanSelectPotions[99].forEach(id => items.push({ id, weight: 100 }));
|
|
||||||
} else {
|
|
||||||
// 全量兜底
|
|
||||||
Object.keys(PotionCards).forEach(key => items.push({ id: Number(key), weight: 100 }));
|
Object.keys(PotionCards).forEach(key => items.push({ id: Number(key), weight: 100 }));
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user