feat: 新增卡牌等级系统并调整英雄合成规则

- 在 HeroAttrsComp 中添加 card_lv 属性,用于独立记录卡牌等级
- 修改 Hero 加载逻辑,支持传入 card_lv 参数
- 更新 HInfoComp 的 UI 刷新逻辑,根据英雄等级和卡牌等级显示不同的边框和等级图标
- 调整 MissionHeroComp 的合成规则:所需合成数量从 2 改为 3,最高合成等级从 3 改为 2
- 在召唤队列和合成流程中传递并处理 card_lv 数据,确保卡牌等级在合成过程中得以保留
This commit is contained in:
panw
2026-04-02 16:40:23 +08:00
parent a14513dcdf
commit 781e88e2d7
6 changed files with 41 additions and 32 deletions

View File

@@ -192,7 +192,8 @@ export class CardComp extends CCComp {
cancel: false,
reason: "",
uuid: this.cardData.uuid,
hero_lv: this.cardData.hero_lv
hero_lv: this.cardData.hero_lv,
card_lv: this.cardData.card_lv
};
oops.message.dispatchEvent(GameEvent.UseHeroCard, guard);
if (guard.cancel) {

View File

@@ -50,7 +50,19 @@ export class HInfoComp extends CCComp {
refresh() {
if (!this.model) return;
this.updateLevelUI();
const isHighLevel = (this.model.lv ?? 0) > 1;
if (this.HF_node) this.HF_node.active = isHighLevel;
if (this.NF_node) this.NF_node.active = !isHighLevel;
const activeFrameNode = isHighLevel ? this.HF_node : this.NF_node;
if (activeFrameNode) {
const cardLvStr = `lv${this.model.card_lv ?? 1}`;
activeFrameNode.children.forEach(child => {
child.active = (child.name === cardLvStr);
});
}
const heroUuid = this.model.hero_uuid ?? 0;
if (heroUuid !== this.iconHeroUuid) {
this.iconHeroUuid = heroUuid;
@@ -87,16 +99,7 @@ export class HInfoComp extends CCComp {
return current.getComponent(Label) || current.getComponentInChildren(Label);
}
private updateLevelUI() {
if (!this.model) return;
const lvNode = this.node.getChildByName("lv");
if (!lvNode) return;
lvNode.active = true
const lv2 = lvNode.getChildByName("lv2");
if (lv2) lv2.active = this.model.lv >= 2;
const lv3 = lvNode.getChildByName("lv3");
if (lv3) lv3.active = this.model.lv >= 3;
}
private updateHeroAnimation(node: Node, uuid: number, token: number) {
if (!node) return;

View File

@@ -234,6 +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)));
if (this.canUseHeroCardByMerge(heroUuid, heroLv)) {
payload.cancel = false;
payload.reason = "";

View File

@@ -31,15 +31,15 @@ export class MissionHeroCompComp extends CCComp {
/** 当前英雄数量缓存 */
current_hero_num:number=-1
/** 合成规则2 合 1 或 3 合 1 */
merge_need_count:number=2
merge_need_count:number=3
/** 允许合成的最高等级 */
merge_max_lv:number=3
merge_max_lv:number=2
/** 是否正在执行一次合成流程 */
is_merging:boolean=false
/** 是否正在消费召唤队列,防止并发处理 */
is_processing_queue:boolean=false
/** 召唤请求队列,保证召唤与合成串行 */
summon_queue:{ uuid: number; hero_lv: number }[]=[]
summon_queue:{ uuid: number; hero_lv: number; card_lv: number }[]=[]
/** 预留英雄列表 */
heros:any=[]
onLoad(){
@@ -84,19 +84,21 @@ export class MissionHeroCompComp extends CCComp {
/** 召唤请求入口:归一化参数并进入串行队列 */
private async call_hero(event: string, args: any){
const uuid = Number(args?.uuid ?? 1001);
const hero_lv = Math.max(1, Number(args?.hero_lv ?? 1));
this.summon_queue.push({ uuid, hero_lv });
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));
this.summon_queue.push({ uuid, hero_lv, card_lv });
this.processSummonQueue();
}
/** 添加英雄:固定出生点上方生成,再落至落点 */
private addHero(uuid:number=1001,hero_lv:number=1) {
private addHero(uuid:number=1001,hero_lv:number=1, card_lv:number=1) {
console.log("addHero uuid:",uuid)
let hero = ecs.getEntity<Hero>(Hero);
let scale = 1
const landingPos = this.resolveHeroLandingPos(uuid);
let spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
hero.load(spawnPos,scale,uuid,landingPos.y,hero_lv);
hero.load(spawnPos,scale,uuid,landingPos.y,hero_lv,card_lv);
return hero;
}
@@ -115,8 +117,8 @@ export class MissionHeroCompComp extends CCComp {
}
/** 添加合成后的新英雄,并覆盖为聚合后的属性 */
private addMergedHero(uuid:number, hero_lv:number, ap:number, hp_max:number): number {
const hero = this.addHero(uuid, hero_lv);
private addMergedHero(uuid:number, hero_lv:number, card_lv:number, ap:number, hp_max:number): number {
const hero = this.addHero(uuid, hero_lv, card_lv);
const model = hero.get(HeroAttrsComp);
if (!model) return hero_lv;
model.ap = Math.max(0, ap);
@@ -184,7 +186,7 @@ export class MissionHeroCompComp extends CCComp {
while (this.summon_queue.length > 0) {
const payload = this.summon_queue.shift();
if (!payload) continue;
await this.handleSingleSummon(payload.uuid, payload.hero_lv);
await this.handleSingleSummon(payload.uuid, payload.hero_lv, payload.card_lv);
}
} finally {
this.is_processing_queue = false;
@@ -192,8 +194,8 @@ export class MissionHeroCompComp extends CCComp {
}
/** 处理单次召唤:先生成,再检测是否触发合成,再尝试链式合成 */
private async handleSingleSummon(uuid: number, hero_lv: number) {
this.addHero(uuid, hero_lv);
private async handleSingleSummon(uuid: number, hero_lv: number, card_lv: number = 1) {
this.addHero(uuid, hero_lv, card_lv);
if (!this.canMergeLevel(hero_lv)) return;
const needCount = this.getMergeNeedCount();
const aliveHeroes = this.getAliveHeroes();
@@ -201,8 +203,8 @@ export class MissionHeroCompComp extends CCComp {
if (mergeHeroes.length !== needCount) return;
this.is_merging = true;
try {
const mergedLv = await this.mergeGroupHeroes(mergeHeroes, uuid, hero_lv);
await this.tryChainMerge(uuid, mergedLv);
const mergedLv = await this.mergeGroupHeroes(mergeHeroes, uuid, hero_lv, card_lv);
await this.tryChainMerge(uuid, mergedLv, card_lv);
} finally {
this.is_merging = false;
}
@@ -256,7 +258,7 @@ export class MissionHeroCompComp extends CCComp {
}
/** 执行一次完整合成:聚合属性、销毁素材、播放特效、生成高一级英雄 */
private async mergeGroupHeroes(mergeHeroes: Hero[], uuid: number, hero_lv: number): Promise<number> {
private async mergeGroupHeroes(mergeHeroes: Hero[], uuid: number, hero_lv: number, card_lv: number): Promise<number> {
let sumAp = 0;
let sumHpMax = 0;
for (let i = 0; i < mergeHeroes.length; i++) {
@@ -269,11 +271,11 @@ export class MissionHeroCompComp extends CCComp {
const spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
await this.mergeDestroyAtBirth(mergeHeroes, spawnPos);
await this.playMergeBoomFx(spawnPos);
return this.addMergedHero(uuid, Math.min(this.merge_max_lv, hero_lv + 1), sumAp, sumHpMax);
return this.addMergedHero(uuid, Math.min(this.merge_max_lv, hero_lv + 1), card_lv, sumAp, sumHpMax);
}
/** 链式合成:当前等级合成完成后,继续尝试更高等级,直到条件不满足 */
private async tryChainMerge(uuid: number, startLv: number) {
private async tryChainMerge(uuid: number, startLv: number, card_lv: number) {
let checkLv = Math.max(1, startLv);
const needCount = this.getMergeNeedCount();
let guard = 0;
@@ -291,7 +293,7 @@ export class MissionHeroCompComp extends CCComp {
if (mergeHeroes.length < needCount) {
break;
}
checkLv = await this.mergeGroupHeroes(mergeHeroes, uuid, checkLv);
checkLv = await this.mergeGroupHeroes(mergeHeroes, uuid, checkLv, card_lv);
}
}