2 Commits

Author SHA1 Message Date
walkpan
882f2b8536 refactor: 优化战斗流程与英雄死亡处理逻辑
1. 移除HeroAttrsComp中多余的空行
2. 修改英雄死亡处理:直接销毁实体而非移至墓地
3. 调整波次更迭逻辑:直接进入BattleStart而非PrepareStart
4. 简化fight_ready方法:移除死亡英雄复活入场逻辑
5. 调整抽卡面板与卡牌池逻辑:战斗阶段保留抽卡面板且仅刷英雄卡
6. 将enterPreparePhase改为public方法
2026-05-15 19:00:11 +08:00
panw
c912e446b1 feat(map): add three new resistance affixes and their handling
1. 新增CritRes、FreezeRes、KnockbackRes三种词缀类型
2. 配置对应词缀的名称、消耗、最低等级等属性
3. 为怪物组件添加词缀抗性属性的赋值逻辑
4. 将新词条加入优先级列表
2026-05-15 16:21:25 +08:00
7 changed files with 42 additions and 38 deletions

View File

@@ -320,7 +320,6 @@ export class HeroAttrsComp extends ecs.Comp {
this.maxSkillDistance = 0;
this.minSkillDistance = 0;
this.is_dead = false;
this.is_count_dead = false;
this.is_atking = false;

View File

@@ -446,14 +446,13 @@ export class HeroViewComp extends CCComp {
}
if(this.model.fac === FacSet.HERO){
// 英雄移到玩家看不到的墓地
this.node.setPosition(v3(-2000, -2000, 0));
// 英雄直接销毁,不再进入墓地
const collider = this.node.getComponent(Collider2D);
if (collider) {
collider.enabled = false;
}
// 隐藏UI
this.top_node.active = false;
this.ent.destroy();
} else {
// 🔥 方案B治理性措施 - 在销毁实体前先禁用碰撞体,从源头减少"尸体"参与碰撞
const collider = this.node.getComponent(Collider2D);

View File

@@ -432,13 +432,6 @@ export class MissionCardComp extends CCComp {
private onUseHeroCard(event: string, args: any) {
const payload = args ?? event;
if (!payload) return;
if (this.isBattlePhase) {
payload.cancel = true;
payload.reason = "battle_phase";
oops.gui.toast("战斗阶段无法召唤英雄");
return;
}
const current = this.getAliveHeroCount();
this.syncMissionHeroData(current);
@@ -671,16 +664,10 @@ export class MissionCardComp extends CCComp {
private enterBattlePhase() {
if (!this.cards_node || !this.cards_node.isValid) return;
this.initCardsPanelPos();
// 战斗阶段不再隐藏抽卡面板
// Tween.stopAllByTarget(this.cards_node);
// tween(this.cards_node)
// .to(this.cardsPanelMoveDuration, { scale: this.cardsHideScale })
// .call(() => {
// if (this.cards_node && this.cards_node.isValid) {
// this.cards_node.active = false;
// }
// })
// .start();
// 战斗阶段抽卡面板不再收起
this.cards_node.active = true;
Tween.stopAllByTarget(this.cards_node);
this.cards_node.setScale(this.cardsShowScale);
this.cachedHInfoComps.forEach(comp => {
if (comp && comp.isValid) {
@@ -693,7 +680,8 @@ export class MissionCardComp extends CCComp {
private buildDrawCards(): CardConfig[] {
let targetType: CardType | CardType[] | undefined = undefined;
if (this.isBattlePhase) {
targetType = CardType.Skill;
// 战斗阶段只刷英雄卡牌,不刷其他卡牌
targetType = CardType.Hero;
} else {
targetType = [CardType.Hero, CardType.SpecialRefresh];
}

View File

@@ -520,9 +520,9 @@ export class MissionComp extends CCComp {
case MissionPhase.BattleEnd:
// BattleEnd 计时结束后,如果是因为全灭或手动调用的 fight_end进入 Settle
// 需要注意的是open_Victory / fight_end 现在只需切换到 BattleEnd 即可Settle 由这里自动接管
// 如果游戏正在运行(波次更迭),则自动进入 PrepareStart 阶段
// 如果游戏正在运行(波次更迭),直接进入下一波的 BattleStart不再进入 PrepareStart
if (smc.mission.play && !smc.mission.pause) {
this.changePhase(MissionPhase.PrepareStart);
this.changePhase(MissionPhase.BattleStart);
} else {
this.changePhase(MissionPhase.Settle);
@@ -566,7 +566,7 @@ export class MissionComp extends CCComp {
* - 显示开始按钮
* - 触发英雄战斗结束技能
*/
private enterPreparePhase() {
enterPreparePhase() {
this.changePhase(MissionPhase.PrepareStart);
}

View File

@@ -121,24 +121,14 @@ export class MissionHeroCompComp extends CCComp {
}
}
/** 战斗准备阶段:重置出战英雄计数,恢复满血重新登场 */
/** 战斗准备阶段:重置出战英雄计数,恢复满血 */
fight_ready(){
const heroes = this.getAllHeroes();
smc.vmdata.mission_data.hero_num = heroes.length;
for (let i = 0; i < heroes.length; i++) {
const hero = heroes[i];
const model = hero.get(HeroAttrsComp);
const view = hero.get(HeroViewComp);
if (model && view) {
if (model.is_dead) {
view.alive();
const landingPos = this.pickPositionForHero([hero.eid]);
// 不再直接设置位置,而是播放下落入场动画
// 计算出出生点(空中)
const spawnPos: Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
view.node.setPosition(spawnPos);
hero.playDropAnim(spawnPos, landingPos.y);
}
if (model) {
model.dirty_hp = true;
}
}

View File

@@ -337,6 +337,19 @@ export class MissionMonCompComp extends CCComp {
// 将词缀记录到属性组件上,供战斗层使用
(model as any).affixes = monData.affixes || [];
// 解析特定的抗性词缀
if (monData.affixes) {
if (monData.affixes.includes(AffixType.CritRes)) {
model.critical_res = 50;
}
if (monData.affixes.includes(AffixType.FreezeRes)) {
model.freeze_res = 50;
}
if (monData.affixes.includes(AffixType.KnockbackRes)) {
model.knockback_res = 50;
}
}
}
/** ECS 组件移除时触发(当前不销毁节点) */

View File

@@ -55,6 +55,9 @@ export enum AffixType {
Giant = 5,
Chain = 6,
SummonerA = 7,
CritRes = 8,
FreezeRes = 9,
KnockbackRes = 10,
}
/**
@@ -113,6 +116,18 @@ export const AffixConfigs: Record<AffixType, AffixConfig> = {
name: "召唤", hpMultiplier: 1.0, apMultiplier: 1.0,
cost: 25, tierMin: 10, description: "每 8 秒召唤 1 个小怪",
},
[AffixType.CritRes]: {
name: "坚韧", hpMultiplier: 1.0, apMultiplier: 1.0,
cost: 15, tierMin: 6, description: "+暴击抗性",
},
[AffixType.FreezeRes]: {
name: "防寒", hpMultiplier: 1.0, apMultiplier: 1.0,
cost: 15, tierMin: 6, description: "+冰冻抗性",
},
[AffixType.KnockbackRes]: {
name: "稳固", hpMultiplier: 1.0, apMultiplier: 1.0,
cost: 15, tierMin: 6, description: "+击退抗性",
},
}
/**
@@ -132,7 +147,7 @@ export const AffixMutualExclusion: AffixType[][] = [
export const AffixPriority: AffixType[] = [
AffixType.Shield, AffixType.Regen, AffixType.Giant,
AffixType.Swift, AffixType.Elite, AffixType.Berserk,
AffixType.Chain, AffixType.SummonerA,
AffixType.Chain, AffixType.SummonerA, AffixType.CritRes, AffixType.FreezeRes, AffixType.KnockbackRes,
]
// ======================== 蓝图模板类型 ========================