1. 重构大招播放方法,支持传入自定义动画clip名,适配不同职业的大招动画 2. 修复技能匹配逻辑,通过前缀匹配处理max0/max1类型的大招技能 3. 更新技能配置表,将辅助职业的技能act改为max1适配新逻辑
116 lines
4.5 KiB
TypeScript
116 lines
4.5 KiB
TypeScript
import { _decorator, Animation, AnimationState, CCClass, Component, } from "cc";
|
||
import { HeroViewComp } from "./HeroViewComp";
|
||
import { FacSet } from "../common/config/GameSet";
|
||
import { FlashSprite } from "./hit-flash-white/scripts/FlashSprite";
|
||
const { ccclass, property } = _decorator;
|
||
|
||
@ccclass('HeroAnmComp')
|
||
export default class HeroAnmComp extends Component {
|
||
fsSprite: FlashSprite = null!;
|
||
private anmcon: any = null
|
||
private _hasStop = true;
|
||
private _atkIndex = 0;
|
||
anms: any[] = ["idle", "move", "atk0", "max0", "max1"]
|
||
onLoad() {
|
||
this.anmcon = this.node.getComponent(Animation)
|
||
this.fsSprite = this.node.getComponent(FlashSprite);
|
||
this.anmcon.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
|
||
}
|
||
|
||
onDestroy() {
|
||
if (this.anmcon) {
|
||
this.anmcon.off(Animation.EventType.FINISHED, this.onAnimationFinished, this);
|
||
}
|
||
}
|
||
|
||
/** 大招是否播放中(最高优先级,期间禁止一切动画切换) */
|
||
private get maxPlaying(): boolean {
|
||
return !!(this.anmcon.getState("max0")?.isPlaying || this.anmcon.getState("max1")?.isPlaying);
|
||
}
|
||
/** 普攻是否播放中(次优先级,仅可被大招打断) */
|
||
private get atkPlaying(): boolean {
|
||
return !!this.anmcon.getState("atk0")?.isPlaying;
|
||
}
|
||
/** buff 是否播放中(可被大招/普攻打断,但拦截 idle/move) */
|
||
private get buffPlaying(): boolean {
|
||
return !!this.anmcon.getState("buff")?.isPlaying;
|
||
}
|
||
|
||
stop() {
|
||
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 统一排序
|
||
if (viewComp) {
|
||
viewComp.isCastingMax = false;
|
||
}
|
||
}
|
||
if (state.name != "idle" && state.name != "move") {
|
||
// 攻击/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();
|
||
}
|
||
/**
|
||
* 播放移动动画。
|
||
* 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")
|
||
return true
|
||
}
|
||
atk() {
|
||
if (this.maxPlaying) return
|
||
this.anmcon.play(`atk0`)
|
||
}
|
||
/**
|
||
* 播放大招动画。
|
||
* Why 带 name:技能表 act 直接配置 clip 名(战士技 "max0"、法系技 "max1"),
|
||
* 固定播 max0 会导致法系大招动画永远播不出。
|
||
* @param name 大招 clip 名("max0"/"max1"),maxPlaying guard 已同时覆盖两者
|
||
*/
|
||
max(name: string = "max0") {
|
||
if (this.maxPlaying) return
|
||
this.anmcon.play(name)
|
||
}
|
||
play(anm: string = "") {
|
||
if (anm === "") return
|
||
if (this.maxPlaying) return
|
||
this.anmcon.play(anm)
|
||
}
|
||
|
||
/**
|
||
* 播放待机动画(返回值语义与 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")
|
||
return true
|
||
}
|
||
buff() {
|
||
if (this.maxPlaying) return
|
||
this.anmcon.play("buff")
|
||
}
|
||
dead() {
|
||
|
||
}
|
||
}
|