fix(map): 修复抽卡重复英雄和英雄站位偏移问题

1. 新增英雄卡UUID去重逻辑,避免单次抽卡出现重复英雄
2. 调整英雄初始站位坐标,修正布局偏移问题
3. 统一代码格式,修复缩进和类型注解不规范问题
This commit is contained in:
pan
2026-07-21 08:53:10 +08:00
parent 89e8f2b091
commit 4d71675c32
2 changed files with 59 additions and 36 deletions

View File

@@ -768,6 +768,7 @@ export class MissionCardComp extends CCComp {
const result: CardConfig[] = []; const result: CardConfig[] = [];
const usedUpgradeTargets = new Set<number>(); const usedUpgradeTargets = new Set<number>();
const usedHeroUuids = new Set<number>();
// 必出 1 张升级卡,按 UUID 升序轮询,放在返回数组首位(对应最左侧卡槽) // 必出 1 张升级卡,按 UUID 升序轮询,放在返回数组首位(对应最左侧卡槽)
if (upgradeCards.length > 0) { if (upgradeCards.length > 0) {
@@ -778,23 +779,36 @@ export class MissionCardComp extends CCComp {
usedUpgradeTargets.add(mandatory.target_hero_eid ?? 0); usedUpgradeTargets.add(mandatory.target_hero_eid ?? 0);
} }
// 剩余张数从混合池抽取,排除已选升级卡 target_hero_eid // 剩余张数从混合池抽取,排除已选升级卡 target_hero_eid 和已选英雄卡 uuid
const remainingCount = 3 - result.length; const remainingCount = 3 - result.length;
if (remainingCount > 0) { if (remainingCount > 0) {
const remainingPool = mixedPool.filter(c => { const remainingPool = mixedPool.filter(c => {
if (c.type === CardType.SpecialUpgrade && c.target_hero_eid) { if (c.type === CardType.SpecialUpgrade && c.target_hero_eid) {
return !usedUpgradeTargets.has(c.target_hero_eid); return !usedUpgradeTargets.has(c.target_hero_eid);
} }
if (c.type === CardType.Hero) {
return !usedHeroUuids.has(c.uuid);
}
return true; return true;
}); });
const rest = this.pickMixedCards(remainingPool, remainingCount, upgradeCards); const rest = this.pickMixedCards(remainingPool, remainingCount, upgradeCards);
result.push(...rest); rest.forEach(c => {
result.push(c);
if (c.type === CardType.SpecialUpgrade && c.target_hero_eid) {
usedUpgradeTargets.add(c.target_hero_eid);
}
if (c.type === CardType.Hero) {
usedHeroUuids.add(c.uuid);
}
});
} }
// 兜底:不足 3 张时循环补齐 // 兜底:不足 3 张时从未使用的英雄卡中补齐,避免出现重复英雄
while (result.length < 3) { while (result.length < 3) {
if (mixedPool.length === 0) break; const fillCard = availableHeroCards.find(c => !usedHeroUuids.has(c.uuid));
result.push(mixedPool[result.length % mixedPool.length]); if (!fillCard) break;
result.push(fillCard);
usedHeroUuids.add(fillCard.uuid);
} }
return result.slice(0, 3); return result.slice(0, 3);
} }
@@ -802,17 +816,22 @@ export class MissionCardComp extends CCComp {
/** /**
* 从混合池中按权重抽取 n 张卡。 * 从混合池中按权重抽取 n 张卡。
* 升级卡之间强制 unique同一个 target_hero_eid 只能出现一次)。 * 升级卡之间强制 unique同一个 target_hero_eid 只能出现一次)。
* 英雄卡之间强制 unique同一个 uuid 只能出现一次),避免同一次发牌出现重复英雄。
*/ */
private pickMixedCards(pool: CardConfig[], count: number, upgradeCards: CardConfig[]): CardConfig[] { private pickMixedCards(pool: CardConfig[], count: number, upgradeCards: CardConfig[]): CardConfig[] {
if (pool.length === 0 || count <= 0) return []; if (pool.length === 0 || count <= 0) return [];
const selected: CardConfig[] = []; const selected: CardConfig[] = [];
const usedUpgradeTargets = new Set<number>(); const usedUpgradeTargets = new Set<number>();
const usedHeroUuids = new Set<number>();
while (selected.length < count) { while (selected.length < count) {
const available = pool.filter(c => { const available = pool.filter(c => {
if (c.type === CardType.SpecialUpgrade && c.target_hero_eid) { if (c.type === CardType.SpecialUpgrade && c.target_hero_eid) {
return !usedUpgradeTargets.has(c.target_hero_eid); return !usedUpgradeTargets.has(c.target_hero_eid);
} }
if (c.type === CardType.Hero) {
return !usedHeroUuids.has(c.uuid);
}
return true; return true;
}); });
if (available.length === 0) break; if (available.length === 0) break;
@@ -822,6 +841,9 @@ export class MissionCardComp extends CCComp {
if (pick.type === CardType.SpecialUpgrade && pick.target_hero_eid) { if (pick.type === CardType.SpecialUpgrade && pick.target_hero_eid) {
usedUpgradeTargets.add(pick.target_hero_eid); usedUpgradeTargets.add(pick.target_hero_eid);
} }
if (pick.type === CardType.Hero) {
usedHeroUuids.add(pick.uuid);
}
} }
return selected; return selected;
} }
@@ -907,6 +929,7 @@ export class MissionCardComp extends CCComp {
count: 3, count: 3,
type: CardType.Hero, type: CardType.Hero,
heroType, heroType,
unique: true, // 保证一次刷新内的英雄卡不重复
}); });
// 过滤掉场上已召唤英雄的普通英雄卡(已召唤的英雄不再重复刷出) // 过滤掉场上已召唤英雄的普通英雄卡(已召唤的英雄不再重复刷出)
const aliveHeroUuids = this.getAliveHeroUuids(); const aliveHeroUuids = this.getAliveHeroUuids();

View File

@@ -49,8 +49,8 @@ export class MissionHeroComp extends CCComp {
/** 硬编码的6个英雄占位点 */ /** 硬编码的6个英雄占位点 */
public static readonly HERO_POSITIONS: Vec3[] = [ public static readonly HERO_POSITIONS: Vec3[] = [
v3(-180, BoxSet.GAME_LINE, 0), // index 0 (node_index 1): Top Front 第二 v3(-200, BoxSet.GAME_LINE, 0), // index 0 (node_index 1): Top Front 第二
v3(-80, BoxSet.GAME_LINE, 0), // index 1 (node_index 2): Mid Front 第一 v3(-120, BoxSet.GAME_LINE, 0), // index 1 (node_index 2): Mid Front 第一
v3(-280, BoxSet.GAME_LINE, 0), // index 2 (node_index 3): Bot Front 第三 v3(-280, BoxSet.GAME_LINE, 0), // index 2 (node_index 3): Bot Front 第三
// v3(-280, BoxSet.GAME_LINE + 100, 0), // index 3 (node_index 4): Top Back // v3(-280, BoxSet.GAME_LINE + 100, 0), // index 3 (node_index 4): Top Back
// v3(-280, BoxSet.GAME_LINE, 0), // index 4 (node_index 5): Mid Back // v3(-280, BoxSet.GAME_LINE, 0), // index 4 (node_index 5): Mid Back