feat: 引入英雄等级提升机制并重构卡牌等级字段
- 将卡牌配置中的 `lv` 字段重命名为 `pool_lv` 以明确表示池等级 - 新增英雄等级提升概率机制,高池等级抽卡有概率获得高英雄等级卡牌 - 更新相关组件以适配新的字段名和英雄等级逻辑 - 修复事件 payload 中 `card_lv` 到 `pool_lv` 的字段映射
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ export interface CardConfig {
|
||||
cost: number
|
||||
weight: number
|
||||
kind: CKind
|
||||
lv: CardLV
|
||||
pool_lv: CardLV
|
||||
hero_lv?: number
|
||||
card_lv?:number
|
||||
}
|
||||
@@ -55,32 +55,35 @@ export const CARD_POOL_MAX_LEVEL = CardLV.LV5
|
||||
/** 英雄最高等级限制 */
|
||||
export const CARD_HERO_MAX_LEVEL = 3
|
||||
/** 基础卡池(英雄、技能、功能) */
|
||||
export const HERO_LV2_INIT_PROB = 0.1
|
||||
export const HERO_LV2_PROB_INC_PER_LV = 0.05
|
||||
|
||||
export const CardPoolList: CardConfig[] = [
|
||||
{ uuid: 5001, type: CardType.Hero, cost: 3, weight: 25, lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5101, type: CardType.Hero, cost: 3, weight: 25, lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5201, type: CardType.Hero, cost: 3, weight: 25, lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5301, type: CardType.Hero, cost: 3, weight: 25, lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5001, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5101, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5201, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5301, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 1, kind: CKind.Hero, hero_lv: 1 },
|
||||
|
||||
{ uuid: 5003, type: CardType.Hero, cost: 3, weight: 25, lv: 2, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5102, type: CardType.Hero, cost: 3, weight: 25, lv: 2, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5302, type: CardType.Hero, cost: 3, weight: 25, lv: 2, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5003, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5102, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5302, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 2, kind: CKind.Hero, hero_lv: 1 },
|
||||
|
||||
{ uuid: 5002, type: CardType.Hero, cost: 3, weight: 25, lv: 3, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5103, type: CardType.Hero, cost: 3, weight: 25, lv: 3, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5202, type: CardType.Hero, cost: 3, weight: 25, lv: 3, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5002, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 3, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5103, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 3, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5202, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 3, kind: CKind.Hero, hero_lv: 1 },
|
||||
|
||||
{ uuid: 5004, type: CardType.Hero, cost: 3, weight: 25, lv: 4, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5104, type: CardType.Hero, cost: 3, weight: 25, lv: 4, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5303, type: CardType.Hero, cost: 3, weight: 25, lv: 4, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5004, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 4, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5104, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 4, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5303, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 4, kind: CKind.Hero, hero_lv: 1 },
|
||||
|
||||
{ uuid: 5105, type: CardType.Hero, cost: 3, weight: 25, lv: 5, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5304, type: CardType.Hero, cost: 3, weight: 25, lv: 5, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5105, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 5, kind: CKind.Hero, hero_lv: 1 },
|
||||
{ uuid: 5304, type: CardType.Hero, cost: 3, weight: 25, pool_lv: 5, kind: CKind.Hero, hero_lv: 1 },
|
||||
|
||||
{ uuid: 7001, type: CardType.SpecialUpgrade, cost: 6, weight: 16, lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7002, type: CardType.SpecialUpgrade, cost: 6, weight: 14, lv: 2 ,kind: CKind.Card },
|
||||
{ uuid: 7101, type: CardType.SpecialRefresh, cost: 4, weight: 14, lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7102, type: CardType.SpecialRefresh, cost: 4, weight: 14, lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7103, type: CardType.SpecialRefresh, cost: 5, weight: 12, lv: 2 ,kind: CKind.Card },
|
||||
{ uuid: 7001, type: CardType.SpecialUpgrade, cost: 6, weight: 16, pool_lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7002, type: CardType.SpecialUpgrade, cost: 6, weight: 14, pool_lv: 2 ,kind: CKind.Card },
|
||||
{ uuid: 7101, type: CardType.SpecialRefresh, cost: 4, weight: 14, pool_lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7102, type: CardType.SpecialRefresh, cost: 4, weight: 14, pool_lv: 1 ,kind: CKind.Card },
|
||||
{ uuid: 7103, type: CardType.SpecialRefresh, cost: 5, weight: 12, pool_lv: 2 ,kind: CKind.Card },
|
||||
]
|
||||
|
||||
|
||||
@@ -111,22 +114,22 @@ export interface SpecialRefreshCardConfig extends CardConfig {
|
||||
|
||||
|
||||
export const SpecialUpgradeCardList: Record<number, SpecialUpgradeCardConfig> = {
|
||||
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 6,weight: 16,lv: CardLV.LV1,kind:CKind.Card,name:"战术晋升",info: "升级场上随机1个1级英雄到2级",
|
||||
7001: { uuid: 7001,type: CardType.SpecialUpgrade,cost: 6,weight: 16,pool_lv: CardLV.LV1,kind:CKind.Card,name:"战术晋升",info: "升级场上随机1个1级英雄到2级",
|
||||
currentLv: 1, targetLv: 2,
|
||||
},
|
||||
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 6,weight: 14,lv: CardLV.LV2,kind:CKind.Card,name:"进阶战术",info: "升级场上随机1个2级英雄到3级",
|
||||
7002: { uuid: 7002,type: CardType.SpecialUpgrade,cost: 6,weight: 14,pool_lv: CardLV.LV2,kind:CKind.Card,name:"进阶战术",info: "升级场上随机1个2级英雄到3级",
|
||||
currentLv: 2, targetLv: 3,
|
||||
},
|
||||
}
|
||||
|
||||
export const SpecialRefreshCardList: Record<number, SpecialRefreshCardConfig> = {
|
||||
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 4,weight: 14,lv: CardLV.LV1,kind:CKind.Card,name:"近战征召",info: "刷新卡池,都是近战英雄",
|
||||
7101: { uuid: 7101,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:"近战征召",info: "刷新卡池,都是近战英雄",
|
||||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Melee,
|
||||
},
|
||||
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 4,weight: 14,lv: CardLV.LV1,kind:CKind.Card,name:"远程征召",info: "刷新卡池,都是远程英雄",
|
||||
7102: { uuid: 7102,type: CardType.SpecialRefresh,cost: 4,weight: 14,pool_lv: CardLV.LV1,kind:CKind.Card,name:"远程征召",info: "刷新卡池,都是远程英雄",
|
||||
refreshLv: 0, refreshHeroType: SpecialRefreshHeroType.Ranged,
|
||||
},
|
||||
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 5,weight: 12,lv: CardLV.LV2,kind:CKind.Card,name:"精英筛选",info: "刷新卡池,都是3级卡池等级英雄",
|
||||
7103: { uuid: 7103,type: CardType.SpecialRefresh,cost: 5,weight: 12,pool_lv: CardLV.LV2,kind:CKind.Card,name:"精英筛选",info: "刷新卡池,都是3级卡池等级英雄",
|
||||
refreshLv: 3, refreshHeroType: SpecialRefreshHeroType.Any,
|
||||
},
|
||||
}
|
||||
@@ -165,13 +168,26 @@ const pickCards = (cards: CardConfig[], count: number): CardConfig[] => {
|
||||
return selected
|
||||
}
|
||||
|
||||
/** 根据概率尝试将抽到的英雄卡的 hero_lv 提升到 2 */
|
||||
const applyHeroLv2Probability = (cards: CardConfig[], currentPoolLv: number): CardConfig[] => {
|
||||
return cards.map(card => {
|
||||
if (card.type === CardType.Hero && card.hero_lv === 1) {
|
||||
const prob = HERO_LV2_INIT_PROB + HERO_LV2_PROB_INC_PER_LV * (currentPoolLv - card.pool_lv)
|
||||
if (Math.random() < prob) {
|
||||
return { ...card, hero_lv: 2 }
|
||||
}
|
||||
}
|
||||
return card
|
||||
})
|
||||
}
|
||||
|
||||
/** 获取指定等级可出现的基础卡池 */
|
||||
export const getCardPoolByLv = (lv: number, onlyCurrentLv: boolean = false): CardConfig[] => {
|
||||
const cardLv = clampCardLv(lv)
|
||||
if (onlyCurrentLv) {
|
||||
return CardPoolList.filter(card => card.lv === cardLv)
|
||||
return CardPoolList.filter(card => card.pool_lv === cardLv)
|
||||
}
|
||||
return CardPoolList.filter(card => card.lv <= cardLv)
|
||||
return CardPoolList.filter(card => card.pool_lv <= cardLv)
|
||||
}
|
||||
|
||||
const normalizeTypeFilter = (type: CardType | CardType[]): Set<CardType> => {
|
||||
@@ -189,13 +205,13 @@ export const getCardsByLv = (
|
||||
if (type !== undefined) {
|
||||
const typeSet = normalizeTypeFilter(type)
|
||||
const filteredPool = pool.filter(card => typeSet.has(card.type))
|
||||
return pickCards(filteredPool, 4)
|
||||
return applyHeroLv2Probability(pickCards(filteredPool, 4), lv)
|
||||
}
|
||||
const heroPool = pool.filter(card => card.type === CardType.Hero)
|
||||
const otherPool = pool.filter(card => card.type !== CardType.Hero)
|
||||
const heroes = pickCards(heroPool, 2)
|
||||
const others = pickCards(otherPool, 2)
|
||||
return [...heroes, ...others]
|
||||
return applyHeroLv2Probability([...heroes, ...others], lv)
|
||||
}
|
||||
|
||||
export const drawCardsByRule = (
|
||||
@@ -225,5 +241,10 @@ export const drawCardsByRule = (
|
||||
return true
|
||||
})
|
||||
}
|
||||
return pickCards(pool, count)
|
||||
const picked = pickCards(pool, count)
|
||||
// 如果明确指定了需要的 heroLv,则不触发升级概率
|
||||
if (options.heroLv !== undefined) {
|
||||
return picked
|
||||
}
|
||||
return applyHeroLv2Probability(picked, lv)
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ export class CardComp extends CCComp {
|
||||
cancel: false,
|
||||
reason: "",
|
||||
uuid: this.cardData.uuid,
|
||||
hero_lv: this.cardData.hero_lv,
|
||||
card_lv: this.cardData.card_lv
|
||||
hero_lv: this.cardData.hero_lv ?? 1,
|
||||
card_lv: this.cardData.pool_lv ?? 1
|
||||
};
|
||||
oops.message.dispatchEvent(GameEvent.UseHeroCard, guard);
|
||||
if (guard.cancel) {
|
||||
@@ -383,14 +383,15 @@ export class CardComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
const cardLvStr = `lv${this.cardData.lv}`;
|
||||
const cardLvStr = `lv${this.cardData.pool_lv}`;
|
||||
if (this.BG_node) {
|
||||
this.BG_node.children.forEach(child => {
|
||||
child.active = (child.name === cardLvStr);
|
||||
});
|
||||
}
|
||||
|
||||
const isHighLevel = (this.cardData.hero_lv ?? 0) > 1 || (this.cardData.card_lv ?? 0) > 1;
|
||||
const card_lv_val = this.cardData.card_lv ?? 1;
|
||||
const isHighLevel = (this.cardData.hero_lv ?? 0) > 1 || card_lv_val > 1;
|
||||
if (this.HF_node) this.HF_node.active = isHighLevel;
|
||||
if (this.NF_node) this.NF_node.active = !isHighLevel;
|
||||
|
||||
@@ -413,7 +414,7 @@ export class CardComp extends CCComp {
|
||||
const specialCard = this.card_type === CardType.SpecialUpgrade
|
||||
? SpecialUpgradeCardList[this.card_uuid]
|
||||
: SpecialRefreshCardList[this.card_uuid];
|
||||
this.setLabel(this.name_node, `${specialCard?.name || ""}Lv.${this.cardData.lv}`);
|
||||
this.setLabel(this.name_node, `${specialCard?.name || ""}Lv.${this.cardData.pool_lv}`);
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = true;
|
||||
this.oinfo_node.getChildByName("info").getComponent(Label).string = `${specialCard?.info || ""}`;
|
||||
|
||||
@@ -234,7 +234,7 @@ export class MissionCardComp extends CCComp {
|
||||
if (current >= heroMax) {
|
||||
const heroUuid = Number(payload?.uuid ?? 0);
|
||||
const heroLv = Math.max(1, Math.floor(Number(payload?.hero_lv ?? 1)));
|
||||
const cardLv = Math.max(1, Math.floor(Number(payload?.card_lv ?? 1)));
|
||||
const cardLv = Math.max(1, Math.floor(Number(payload?.pool_lv ?? 1)));
|
||||
if (this.canUseHeroCardByMerge(heroUuid, heroLv)) {
|
||||
payload.cancel = false;
|
||||
payload.reason = "";
|
||||
|
||||
@@ -87,7 +87,7 @@ export class MissionHeroCompComp extends CCComp {
|
||||
const payload = args ?? event;
|
||||
const uuid = Number(payload?.uuid ?? 1001);
|
||||
const hero_lv = Math.max(1, Number(payload?.hero_lv ?? 1));
|
||||
const card_lv = Math.max(1, Number(payload?.card_lv ?? 1));
|
||||
const card_lv = Math.max(1, Number(payload?.pool_lv ?? 1));
|
||||
this.summon_queue.push({ uuid, hero_lv, card_lv });
|
||||
this.processSummonQueue();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user