消消方块阵换皮表情
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

137 lines
4.6 KiB

import { _decorator, Component, Node } from 'cc';
import { Monster } from './Monster';
import { GEvent } from 'db://assets/mx/module/event/GEvent';
import { GBundle } from '../../game/ConfigRes';
import { BossSkill } from './BossSkill';
const { ccclass, property } = _decorator;
@ccclass('Boss')
export class Boss extends Component {
@property(Node)
startPosNode: Node = null;
monster: Monster;
protected onEnable(): void {
GEvent.Ins.on(GEvent.tetriGameStart, this.onBossStart, this);
GEvent.Ins.on(GEvent.BattleWarnTimeStart, this.onBattleWarnTimeStart, this);
}
protected onDisable(): void {
GEvent.Ins.off(GEvent.tetriGameStart, this.onBossStart, this);
GEvent.Ins.off(GEvent.BattleWarnTimeStart, this.onBattleWarnTimeStart, this);
}
setMonster(monster: Monster) {
this.monster = monster;
this.playWaitAnim();
// 预热 Boss 投掷物,避免 useskillwave 触发时 getNode 同步未命中返回 null
void gg.res.ensurePrefab('bossWeapon1', 'prefab/武器/', GBundle.BattleGameWeapon);
void gg.res.ensurePrefab('砖块爆炸', 'prefab/爆炸/', GBundle.BattleGameWeapon);
}
/**战斗警告时间开始 */
onBattleWarnTimeStart() {
this.scheduleOnce(() => {
if (!this.monster?.Data?.useskillwave) return;
let wNum = gg.game.CurentBattle.CurentWaveNum;
if (this.monster.Data.useskillwave.includes(wNum)) {
this.playAttackAnim(() => {
this.playWaitAnim();
});
void this.atk();
}
}, 4.8);
}
onBossStart() {
if (!this.monster) return;
this.playSummonAnim(() => {
this.playWaitAnim();
});
}
async atk() {
const battle = gg.game?.CurentBattle;
if (!battle) return;
const parent =
battle.SkillController?.node?.isValid
? battle.SkillController.node
: battle.TetraMap?._gameRoot?.isValid
? battle.TetraMap._gameRoot
: null;
if (!parent) {
console.warn('[Boss.atk] SkillController / GameRoot 均不可用,跳过投掷');
return;
}
let startPos = this.startPosNode ? this.startPosNode.worldPosition : this.node.worldPosition;
let targetPos = this.getHighestBlockWorldPos();
let n = await gg.res.getNodeAsync('prefab/武器/', 'bossWeapon1', GBundle.BattleGameWeapon);
if (!n?.isValid) {
console.warn('[Boss.atk] bossWeapon1 加载失败');
return;
}
n.setParent(parent, true);
n.worldPosition = startPos;
let comp = n.getComponent(BossSkill);
if (!comp) {
console.warn('[Boss.atk] bossWeapon1 缺少 BossSkill');
gg.res.putNode(n);
return;
}
comp.setData(this.monster, targetPos);
}
/**获取当前堆叠的方块中最高的那个方块的世界坐标 */
getHighestBlockWorldPos() {
let nodes = gg.game.CurentBattle?.TetraMap?._tetrisTable?.children;
if (!nodes?.length) {
return this.startPosNode ? this.startPosNode.worldPosition.clone() : this.node.worldPosition.clone();
}
let highestBlock = nodes.reduce((max, node) => {
return node.worldPosition.y > max.worldPosition.y ? node : max;
}, nodes[0]);
return highestBlock.worldPosition;
}
/**播放待机动画 */
playWaitAnim() {
this.playSpine('1待机', null, 1, true);
}
/**播放抛完待机 */
playAfterThrowWaitAnim() {
this.playSpine('4抛完待机', null, 1, true);
}
/**播放召唤动画 */
playSummonAnim(callback: Function = null) {
gg.audio.playEffect({ name: 'BOSS吼叫', path: 'sound/武器音效2/' });
this.playSpine('2召唤', callback, 1, false);
}
/**播放攻击动画 */
playAttackAnim(callback: Function = null) {
this.playSpine('3攻击', callback, 1, false);
}
/**播放Spine动画 */
playSpine(name: string, callback: Function = null, timeScale = 1, loop = true) {
if (!this.monster.anim) {
if (callback) callback();
return;
}
this.monster.anim.timeScale = timeScale * gg.game.CurentBattle.TimeScale;
this.monster.anim.setAnimation(0, name, loop);
if (callback) {
this.monster.anim.setCompleteListener(() => {
this.monster.anim.setCompleteListener(null);
callback();
});
}
}
}