feat(英雄合并): 支持三合一合并并实现链式合并

- 将合并条件从两个英雄改为三个英雄
- 重构合并逻辑,提取 mergeGroupHeroes 方法处理合并过程
- 新增链式合并功能,当满足条件时自动触发连续合并
- 添加 countMergeHeroes 方法统计可合并英雄数量
- 优化代码结构,提高可维护性
This commit is contained in:
panw
2026-03-27 14:49:44 +08:00
parent 23f4de0c1e
commit e57ecca665

View File

@@ -58,34 +58,22 @@ export class MissionHeroCompComp extends CCComp {
} }
private async call_hero(event: string, args: any){ private async call_hero(event: string, args: any){
if (this.is_merging) return;
const uuid = Number(args?.uuid ?? 1001); const uuid = Number(args?.uuid ?? 1001);
const hero_lv = Math.max(1, Number(args?.hero_lv ?? 1)); const hero_lv = Math.max(1, Number(args?.hero_lv ?? 1));
this.addHero(uuid, hero_lv);
const aliveHeroes = this.getAliveHeroes(); const aliveHeroes = this.getAliveHeroes();
const mergeHeroes = this.pickMergeHeroes(aliveHeroes, uuid, hero_lv); const mergeHeroes = this.pickMergeHeroes(aliveHeroes, uuid, hero_lv, 3);
if (mergeHeroes.length === 2) { if (mergeHeroes.length === 3) {
if (this.is_merging) return;
this.is_merging = true; this.is_merging = true;
try { try {
let sumAp = 0; const mergedLv = await this.mergeGroupHeroes(mergeHeroes, uuid, hero_lv);
let sumHpMax = 0; await this.tryChainMerge(uuid, mergedLv);
for (let i = 0; i < mergeHeroes.length; i++) {
const model = mergeHeroes[i].get(HeroAttrsComp);
if (!model) continue;
sumAp += model.ap;
sumHpMax += model.hp_max;
}
let hero_pos = 0;
const landingPos:Vec3 = HeroPos[hero_pos].pos;
const spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
await this.mergeDestroyAtBirth(mergeHeroes, spawnPos);
await this.playMergeBoomFx(spawnPos);
this.addMergedHero(uuid, hero_lv + 1, sumAp, sumHpMax);
} finally { } finally {
this.is_merging = false; this.is_merging = false;
} }
return; return;
} }
this.addHero(uuid, hero_lv);
} }
/** 添加英雄 */ /** 添加英雄 */
private addHero(uuid:number=1001,hero_lv:number=1) { private addHero(uuid:number=1001,hero_lv:number=1) {
@@ -99,14 +87,15 @@ export class MissionHeroCompComp extends CCComp {
return hero; return hero;
} }
private addMergedHero(uuid:number, hero_lv:number, ap:number, hp_max:number) { private addMergedHero(uuid:number, hero_lv:number, ap:number, hp_max:number): number {
const hero = this.addHero(uuid, hero_lv); const hero = this.addHero(uuid, hero_lv);
const model = hero.get(HeroAttrsComp); const model = hero.get(HeroAttrsComp);
if (!model) return; if (!model) return hero_lv;
model.ap = Math.max(0, ap); model.ap = Math.max(0, ap);
model.hp_max = Math.max(1, hp_max); model.hp_max = Math.max(1, hp_max);
model.hp = model.hp_max; model.hp = model.hp_max;
model.dirty_hp = true; model.dirty_hp = true;
return model.lv;
} }
private getAliveHeroes(): Hero[] { private getAliveHeroes(): Hero[] {
@@ -121,7 +110,7 @@ export class MissionHeroCompComp extends CCComp {
return heroes; return heroes;
} }
private pickMergeHeroes(aliveHeroes: Hero[], uuid: number, hero_lv: number): Hero[] { private pickMergeHeroes(aliveHeroes: Hero[], uuid: number, hero_lv: number, needCount: number = 3): Hero[] {
const mergeHeroes: Hero[] = []; const mergeHeroes: Hero[] = [];
for (let i = 0; i < aliveHeroes.length; i++) { for (let i = 0; i < aliveHeroes.length; i++) {
const model = aliveHeroes[i].get(HeroAttrsComp); const model = aliveHeroes[i].get(HeroAttrsComp);
@@ -129,11 +118,23 @@ export class MissionHeroCompComp extends CCComp {
if (model.hero_uuid !== uuid) continue; if (model.hero_uuid !== uuid) continue;
if (model.lv !== hero_lv) continue; if (model.lv !== hero_lv) continue;
mergeHeroes.push(aliveHeroes[i]); mergeHeroes.push(aliveHeroes[i]);
if (mergeHeroes.length === 2) break; if (mergeHeroes.length === needCount) break;
} }
return mergeHeroes; return mergeHeroes;
} }
private countMergeHeroes(aliveHeroes: Hero[], uuid: number, hero_lv: number): number {
let count = 0;
for (let i = 0; i < aliveHeroes.length; i++) {
const model = aliveHeroes[i].get(HeroAttrsComp);
if (!model) continue;
if (model.hero_uuid !== uuid) continue;
if (model.lv !== hero_lv) continue;
count += 1;
}
return count;
}
private mergeDestroyAtBirth(mergeHeroes: Hero[], spawnPos: Vec3): Promise<void> { private mergeDestroyAtBirth(mergeHeroes: Hero[], spawnPos: Vec3): Promise<void> {
return new Promise((resolve) => { return new Promise((resolve) => {
let doneCount = 0; let doneCount = 0;
@@ -179,6 +180,41 @@ export class MissionHeroCompComp extends CCComp {
}); });
} }
private async mergeGroupHeroes(mergeHeroes: Hero[], uuid: number, hero_lv: number): Promise<number> {
let sumAp = 0;
let sumHpMax = 0;
for (let i = 0; i < mergeHeroes.length; i++) {
const model = mergeHeroes[i].get(HeroAttrsComp);
if (!model) continue;
sumAp += model.ap;
sumHpMax += model.hp_max;
}
let hero_pos = 0;
const landingPos:Vec3 = HeroPos[hero_pos].pos;
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, hero_lv + 1, sumAp, sumHpMax);
}
private async tryChainMerge(uuid: number, startLv: number) {
let checkLv = Math.max(1, startLv);
let guard = 0;
while (guard < 20) {
guard += 1;
const aliveHeroes = this.getAliveHeroes();
const sameCount = this.countMergeHeroes(aliveHeroes, uuid, checkLv);
if (sameCount < 3) {
break;
}
const mergeHeroes = this.pickMergeHeroes(aliveHeroes, uuid, checkLv, 3);
if (mergeHeroes.length < 3) {
break;
}
checkLv = await this.mergeGroupHeroes(mergeHeroes, uuid, checkLv);
}
}