From 89e8f2b0918ca96f778f2cbc382ff926220d3a7a Mon Sep 17 00:00:00 2001 From: panFD Date: Tue, 21 Jul 2026 08:09:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(map):=20=E6=96=B0=E5=A2=9E=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E5=8F=AC=E5=94=A4=E8=8B=B1=E9=9B=84=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E4=B8=8E=E6=8A=BD=E5=8D=A1=E8=BF=87=E6=BB=A4=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增英雄召唤重复校验,防止已召唤英雄被再次召唤;同时优化抽卡逻辑,不再刷出已召唤英雄的普通卡牌,仅可通过升级卡升级已召唤英雄。 --- assets/script/game/map/MissionCardComp.ts | 30 ++++++++++++++++++++--- assets/script/game/map/MissionHeroComp.ts | 24 ++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/assets/script/game/map/MissionCardComp.ts b/assets/script/game/map/MissionCardComp.ts index e3b4ea78..0c56dae1 100644 --- a/assets/script/game/map/MissionCardComp.ts +++ b/assets/script/game/map/MissionCardComp.ts @@ -758,9 +758,12 @@ export class MissionCardComp extends CCComp { } const heroCards = CardPoolList.filter(c => c.type === CardType.Hero); + // 过滤掉场上已召唤英雄的普通英雄卡:已召唤的英雄只能通过升级卡升级,不再刷出普通卡 + const aliveHeroUuids = this.getAliveHeroUuids(); + const availableHeroCards = heroCards.filter(c => !aliveHeroUuids.has(c.uuid)); - // 英雄池只刷英雄卡(含动态升级卡),不再混入刷新功能卡 - const mixedPool: CardConfig[] = [...upgradeCards, ...heroCards]; + // 英雄池只刷英雄卡(含动态升级卡 + 未召唤英雄的普通卡) + const mixedPool: CardConfig[] = [...upgradeCards, ...availableHeroCards]; if (mixedPool.length === 0) return []; const result: CardConfig[] = []; @@ -905,9 +908,12 @@ export class MissionCardComp extends CCComp { type: CardType.Hero, heroType, }); - if (cards.length <= 0) return false; + // 过滤掉场上已召唤英雄的普通英雄卡(已召唤的英雄不再重复刷出) + const aliveHeroUuids = this.getAliveHeroUuids(); + const available = cards.filter(c => !aliveHeroUuids.has(c.uuid)); + if (available.length <= 0) return false; this.layoutCardSlots(); - this.dispatchCardsToSlots(cards.slice(0, 3)); + this.dispatchCardsToSlots(available.slice(0, 3)); return true; } @@ -1081,6 +1087,22 @@ export class MissionCardComp extends CCComp { return actors; } + /** + * 获取场上所有存活英雄的 hero_uuid 集合。 + * 用于抽卡时过滤:已召唤的英雄不再从普通英雄卡池中刷出,只能通过升级卡升级。 + */ + private getAliveHeroUuids(): Set { + const uuids = new Set(); + ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => { + const model = entity.get(HeroAttrsComp); + if (!model) return; + if (model.fac !== FacSet.HERO) return; + if (model.is_dead) return; + uuids.add(model.hero_uuid); + }); + return uuids; + } + /** * 按 eid 精确升级场上对应英雄实体。 * diff --git a/assets/script/game/map/MissionHeroComp.ts b/assets/script/game/map/MissionHeroComp.ts index 2ecf339e..75ba0add 100644 --- a/assets/script/game/map/MissionHeroComp.ts +++ b/assets/script/game/map/MissionHeroComp.ts @@ -142,6 +142,7 @@ export class MissionHeroComp extends CCComp { /** * 召唤请求入口: * 从事件参数中提取 uuid / hero_lv / pool_lv,放入串行队列。 + * 防御:已召唤的英雄 uuid 拒绝重复召唤(只能通过升级卡升级)。 * * @param event 事件名 * @param args { uuid, hero_lv, pool_lv } @@ -151,10 +152,33 @@ export class MissionHeroComp extends CCComp { const uuid = Number(payload?.uuid ?? 1001); const hero_lv = Math.max(1, Number(payload?.hero_lv ?? 1)); const pool_lv = Math.max(1, Number(payload?.pool_lv ?? 1)); + + // 防御:场上已有同 uuid 的存活英雄时,拒绝重复召唤 + if (this.isHeroAlreadySummoned(uuid)) { + oops.gui.toast(`该英雄已召唤,只能通过升级卡升级`); + return; + } + this.summon_queue.push({ uuid, hero_lv, pool_lv }); this.processSummonQueue(); } + /** + * 检查场上是否已存在指定 uuid 的存活英雄。 + * @param uuid 英雄模板 uuid + * @returns true 表示场上已有该英雄,不可重复召唤 + */ + private isHeroAlreadySummoned(uuid: number): boolean { + let exists = false; + ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => { + if (exists) return; + const model = entity.get(HeroAttrsComp); + if (!model || model.fac !== FacSet.HERO || model.is_dead) return; + if (model.hero_uuid === uuid) exists = true; + }); + return exists; + } + // ======================== 英雄生成 ======================== /**