Compare commits
2 Commits
aafbd6eff9
...
d951896799
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d951896799 | ||
|
|
1fc91dce21 |
@@ -143,17 +143,7 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
shop: false, // 购买药品面板按钮
|
||||
},
|
||||
/** 英雄局外成长数据:记录每个英雄的局外等级与碎片数量 */
|
||||
// TODO: 以下为测试英雄升级功能的模拟数据,验证通过后需移除(避免污染云端存档)
|
||||
hero_growth: {
|
||||
// 碎片充足:可连升 2 级(10+20=30,剩余 20 不够升 4 级)
|
||||
5001: { uuid: 5001, lv: 1, fragments: 50 },
|
||||
// 碎片不足:升 4 级需 40,验证升级失败路径
|
||||
5002: { uuid: 5002, lv: 3, fragments: 15 },
|
||||
// 碎片刚好够升到满级:升 6 级需 160
|
||||
5003: { uuid: 5003, lv: 5, fragments: 160 },
|
||||
// 已满级:验证满级后 upgradeHero 返回 false
|
||||
5004: { uuid: 5004, lv: 6, fragments: 999 },
|
||||
} as Record<number, HeroGrowthRecord>,
|
||||
hero_growth: {} as Record<number, HeroGrowthRecord>,
|
||||
/** 天赋等级表:key 为天赋 uuid,value 为当前等级 */
|
||||
talents: {} as Record<number, number>,
|
||||
/** 可用天赋点数 */
|
||||
|
||||
@@ -10,7 +10,6 @@ export default class HeroAnmComp extends Component {
|
||||
private anmcon: any = null
|
||||
private _hasStop = true;
|
||||
private _atkIndex = 0;
|
||||
private default_anim: string = 'idle'
|
||||
anms: any[] = ["idle", "move", "atk0", "max0", "max1"]
|
||||
onLoad() {
|
||||
this.anmcon = this.node.getComponent(Animation)
|
||||
@@ -41,25 +40,41 @@ export default class HeroAnmComp extends Component {
|
||||
this._hasStop = true;
|
||||
}
|
||||
onAnimationFinished(type: Animation.EventType, state: AnimationState) {
|
||||
// HeroAnmComp 与 HeroViewComp 挂在同一节点上,直接 getComponent 即可,
|
||||
// 不需要走父节点查找(且 Component 没有 getComponentInParent,必须在 Node 上调用)
|
||||
const viewComp = this.node.getComponent(HeroViewComp);
|
||||
if (state.name === "max0" || state.name === "max1") {
|
||||
// 大招播放结束,清除 HeroViewComp 的置顶标记,恢复 MoveSystem 统一排序
|
||||
const viewComp = this.node.getComponent(HeroViewComp) || this.node.getComponentInParent(HeroViewComp);
|
||||
if (viewComp) {
|
||||
viewComp.isCastingMax = false;
|
||||
}
|
||||
}
|
||||
if (state.name != "idle" && state.name != "move") {
|
||||
this.anmcon.play(this.default_anim)
|
||||
// 攻击/buff/大招结束:按视图层记录的真实状态回放,而非过期的缓存动画,
|
||||
// 避免"位置已停但还在播走路"的原地走步(view.status 由 status_change 成功切换时写入)
|
||||
const target = viewComp?.status === "move" ? "move" : "idle";
|
||||
if (!this.maxPlaying && !this.atkPlaying && !this.buffPlaying) {
|
||||
if (!this.anmcon.getState(target)?.isPlaying) {
|
||||
this.anmcon.play(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
atked() {
|
||||
this.fsSprite.clickFlash();
|
||||
}
|
||||
move() {
|
||||
if (this.maxPlaying || this.atkPlaying || this.buffPlaying) return
|
||||
if (this.anmcon.getState("move").isPlaying) return
|
||||
/**
|
||||
* 播放移动动画。
|
||||
* Why 返回 boolean:普攻/buff/大招播放期间会被拦截(return false),
|
||||
* 调用方(HeroSpine/HeroViewComp)据此不记录状态,保证记录状态与实际动画一致,
|
||||
* 下一帧重试时去重条件不成立可再次尝试,避免"位置在动但动画卡死"。
|
||||
* @returns true = 动画已处于目标状态(新播或原本在播);false = 被高优先级动画拦截
|
||||
*/
|
||||
move(): boolean {
|
||||
if (this.maxPlaying || this.atkPlaying || this.buffPlaying) return false
|
||||
if (this.anmcon.getState("move").isPlaying) return true
|
||||
this.anmcon.play("move")
|
||||
this.default_anim = 'move'
|
||||
return true
|
||||
}
|
||||
atk() {
|
||||
if (this.maxPlaying) return
|
||||
@@ -75,11 +90,14 @@ export default class HeroAnmComp extends Component {
|
||||
this.anmcon.play(anm)
|
||||
}
|
||||
|
||||
idle() {
|
||||
if (this.maxPlaying || this.atkPlaying || this.buffPlaying) return
|
||||
if (this.anmcon.getState("idle").isPlaying) return
|
||||
/**
|
||||
* 播放待机动画(返回值语义与 move() 一致:被高优先级动画拦截时返回 false)
|
||||
*/
|
||||
idle(): boolean {
|
||||
if (this.maxPlaying || this.atkPlaying || this.buffPlaying) return false
|
||||
if (this.anmcon.getState("idle").isPlaying) return true
|
||||
this.anmcon.play("idle")
|
||||
this.default_anim = 'idle'
|
||||
return true
|
||||
}
|
||||
buff() {
|
||||
if (this.maxPlaying) return
|
||||
|
||||
@@ -35,11 +35,15 @@ export class HeroSpine extends Component {
|
||||
|
||||
|
||||
}
|
||||
idle(){
|
||||
|
||||
if(this.status=="idle") return
|
||||
/**
|
||||
* 播放待机动画:动画层成功切换才记录 status,
|
||||
* 被普攻/buff/大招拦截时返回 false 且不记录,保证记录与实际动画一致。
|
||||
*/
|
||||
idle(): boolean {
|
||||
if(this.status=="idle") return true
|
||||
if(!this.anm.idle()) return false
|
||||
this.status="idle"
|
||||
this.anm.idle()
|
||||
return true
|
||||
}
|
||||
atk() {
|
||||
this.anm.atk()
|
||||
@@ -75,10 +79,12 @@ export class HeroSpine extends Component {
|
||||
buff(){
|
||||
this.anm.buff()
|
||||
}
|
||||
move(){
|
||||
if(this.status=="move") return
|
||||
/** 播放移动动画(返回值语义与 idle() 一致:拦截时不记录状态) */
|
||||
move(): boolean {
|
||||
if(this.status=="move") return true
|
||||
if(!this.anm.move()) return false
|
||||
this.status="move"
|
||||
this.anm.move()
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -312,15 +312,24 @@ export class HeroViewComp extends CCComp {
|
||||
get isActive() {
|
||||
return this.ent.has(HeroViewComp) && this.node?.isValid;
|
||||
}
|
||||
/** 状态切换(动画) */
|
||||
/**
|
||||
* 状态切换(动画)。
|
||||
* Why 成功才记录:动画层在普攻/buff/大招播放期间会拦截 idle/move 切换,
|
||||
* 若先记录状态再播动画,会导致记录与实际动画永久脱钩(位置在动动画却卡死、
|
||||
* 或攻击结束回放过期动画)。只在切换成功时写入 status,被拦截时不写入,
|
||||
* 下一帧 MoveSystem 重试时去重条件不成立,会再次尝试直至成功。
|
||||
*/
|
||||
status_change(type: string) {
|
||||
if (this.status === type) return;
|
||||
if (this.model.is_dead || this.model.is_reviving) {
|
||||
// 死亡/复活中动画由对应流程接管,仅记录待恢复状态
|
||||
this.status = type;
|
||||
if (this.model.is_dead || this.model.is_reviving) return
|
||||
return;
|
||||
}
|
||||
if (type === "idle") {
|
||||
this.as.idle();
|
||||
if (this.as.idle()) this.status = type;
|
||||
} else if (type === "move") {
|
||||
this.as.move();
|
||||
if (this.as.move()) this.status = type;
|
||||
}
|
||||
}
|
||||
/** 护盾常驻特效节点,避免重复创建 */
|
||||
@@ -374,6 +383,9 @@ export class HeroViewComp extends CCComp {
|
||||
// 恢复UI
|
||||
this.topBar.show();
|
||||
|
||||
// 死亡期间 status 可能已被记录为 idle(死亡分支只记录不播动画),
|
||||
// 清空强制重同步,确保复活后动画真实切回待机
|
||||
this.status = "";
|
||||
this.status_change("idle");
|
||||
|
||||
// 【新增】仅英雄阵营派发复活成功事件,供卡牌技能(HeroCall 类型)监听
|
||||
|
||||
@@ -131,7 +131,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
model.is_atking = false;
|
||||
if (model.fac === FacSet.HERO) {
|
||||
this.processHeroQueue(e, model, move, view);
|
||||
} else if (view.status !== "atk") {
|
||||
} else {
|
||||
view.status_change("idle");
|
||||
}
|
||||
return;
|
||||
@@ -146,7 +146,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
/** 无敌人:停止移动,等待战斗结束结算 */
|
||||
this.clearCombatTarget(model);
|
||||
model.is_atking = false;
|
||||
if (view.status !== "atk") view.status_change("idle");
|
||||
view.status_change("idle");
|
||||
}
|
||||
|
||||
/** 渲染层级重排(双阵营统一处理) */
|
||||
@@ -181,7 +181,7 @@ export class MoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
view.node.setPosition(targetX, view.node.position.y, 0);
|
||||
}
|
||||
view.scale = 1;
|
||||
if (view.status !== "atk") view.status_change("idle");
|
||||
view.status_change("idle");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -842,15 +842,26 @@ export class VictoryComp extends CCComp {
|
||||
|
||||
/**
|
||||
* 确认按钮点击(代码绑定,btns/btn):
|
||||
* - 小节胜利(section)→ 派发 NextSection 推进下一节(修复:之前直接 MissionEnd 导致关卡未推进)
|
||||
* - 小节胜利(section)→ 推进存档到下一节并保存 → 派发 MissionEnd → 关闭结算弹窗
|
||||
* - 末关通关(final) → 清理数据 → 派发 MissionEnd → 关闭结算弹窗
|
||||
* - 失败(defeat) → 清理数据 → 派发 MissionEnd → 关闭结算弹窗
|
||||
*
|
||||
* Why: 小节胜利点"退出"既要保存进度(避免下次重玩卡在原节),
|
||||
* 又不能像"下一节"按钮那样直接开战(玩家已选退出,不再继续本局战斗)。
|
||||
*/
|
||||
victory_end() {
|
||||
if (this.settleType === "section") {
|
||||
// 小节胜利:与"下一节"按钮行为一致,避免胜利后点退出直接结束关卡
|
||||
oops.message.dispatchEvent(GameEvent.NextSection);
|
||||
return;
|
||||
// 小节胜利:手动推进 section 到下一节并保存存档,避免点退出后进度丢失。
|
||||
// 注:MissionComp 的 NextSection 会进入战斗流程,这里不走该事件以避免自动开战。
|
||||
const cur = (smc.data.stage_progress ?? { chapter: 1, stage: 1, section: 1 }) as { chapter: number; stage: number; section: number };
|
||||
// 当前节已胜利,写入下一节作为待挑战存档;若已是末节(section=10),则不做 section 推进
|
||||
if (cur.section < 10) {
|
||||
smc.updateStageProgress({
|
||||
chapter: cur.chapter,
|
||||
stage: cur.stage,
|
||||
section: cur.section + 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
this.clear_data()
|
||||
oops.message.dispatchEvent(GameEvent.MissionEnd)
|
||||
|
||||
Reference in New Issue
Block a user