import { _decorator, Component, find, Node, sp, Tween, tween, v3, Vec3 } from 'cc'; import { tetriWeaponCarrier } from '../tetriCard/tetriWeaponCarrier'; import { GEvent } from '../../mx/module/event/GEvent'; const { ccclass, property } = _decorator; @ccclass('jiujiuwoMap') export class jiujiuwoMap extends Component { /**出怪口 */ public spawnPointParent: Node = null; public _gameRoot: Node = null; timeHit: number = 0; /** 上次已切换到的喷泉档位 0~3(与血量分段一致),-1 表示尚未与城墙血量同步 */ private _lastFountainTier: number = -1; meinvAnimState: string = '待机'; start() { this._initNodes(); } onEnable(){ GEvent.Ins.on(GEvent.playerHit, this._onPlayerHit, this); } onDisable(){ GEvent.Ins.off(GEvent.playerHit, this._onPlayerHit, this); } /**初始状态喷泉和美女*/ initState(){ const wallTarget1 = find('目标点/wallTarget1', this.node); if (!wallTarget1 || !wallTarget1.isValid) { return; } this._lastFountainTier = -1; this.showMeinvIdleEffect(); this._updateWallFountainDisplay(); } _initNodes(){ if (this._gameRoot) return; this._gameRoot = find("GameRoot", this.node); if (!this._gameRoot) return; this.spawnPointParent = this.node.getChildByName('出怪口'); if (this.spawnPointParent.getChildByName('spawnPoint_4')) { this.spawnPointParent.getChildByName('spawnPoint_4').x = 360; this.spawnPointParent.getChildByName('spawnPoint_4').y = -356 } if (this.spawnPointParent.getChildByName('spawnPoint_5')) { this.spawnPointParent.getChildByName('spawnPoint_5').x = 360; this.spawnPointParent.getChildByName('spawnPoint_5').y = -401 } if (this.spawnPointParent.getChildByName('spawnPoint_6')) { this.spawnPointParent.getChildByName('spawnPoint_6').x = 360; this.spawnPointParent.getChildByName('spawnPoint_6').y = -401 } } /**获取目标点*/ public getPathShortestTarget(startPos: Vec3): Node { const n1 = find('目标点/wallTarget1', this.node); return n1; } /***获取_tetrisTable的子节点数量*/ getTetriNodeCount(){ return 0 } //******美女胜利动画******/ showMeinvWinEffect(){ const wallTarget1 = find('目标点/wallTarget1', this.node); if(!wallTarget1 || !wallTarget1.isValid){ return; } if(this.timeHit){ clearTimeout(this.timeHit); } let meinv = wallTarget1.getChildByName('美女'); if(meinv?.isValid){ this.meinvAnimState = '胜利'; meinv.getComponent(sp.Skeleton).setAnimation(0, '胜利', true) } } /**遍历场上武器载体,找到对应 weaponId(救救我鸭为直挂角色,可能多个)*/ getTetriWeaponCarrier(weaponId: number): tetriWeaponCarrier[] { const carriers = gg.game?.CurentBattle?.jiujiuwoyaWeaponCarriers ?? []; return carriers.filter(c => c?.node?.isValid && c.getCurWeaponId() === weaponId); } //美女待机 showMeinvIdleEffect() { const wallTarget1 = find('目标点/wallTarget1', this.node); if(!wallTarget1 || !wallTarget1.isValid){ return; } let meinv = wallTarget1.getChildByName('美女'); if(meinv?.isValid){ this.meinvAnimState = '待机'; meinv.getComponent(sp.Skeleton).setAnimation(0, '待机', true) } } showQiPaoEffect() { const wallTarget1 = find('目标点/wallTarget1', this.node); if(!wallTarget1 || !wallTarget1.isValid){ return; } let qipao = wallTarget1.getChildByName('气泡文字'); let meinv = wallTarget1.getChildByName('美女'); if (qipao?.isValid) { if(this.timeHit){ clearTimeout(this.timeHit); } meinv.getComponent(sp.Skeleton).setAnimation(0, '说话', true) this.meinvAnimState = '说话'; qipao.active = true; qipao.scale = v3(0, 0, 0); tween(qipao) .to(0.5, { scale: v3(0.55, 0.55, 0.55) }, { easing: 'quadInOut' }) .delay(3.0) .call(() => { this.hideQiPaoEffect(); this.showMeinvIdleEffect(); }) .start(); } } hideQiPaoEffect() { const wallTarget1 = find('目标点/wallTarget1', this.node); let qipao = wallTarget1.getChildByName('气泡文字'); if (qipao?.isValid) { qipao.active = false; } } /** * 100%~75%:喷泉;75%~50%:喷泉2;50%~25%:喷泉3;25%~0%:喷泉4。 * 档位切换时:将要显示的一层从透明淡入,原先显示的一层同时淡出至 0 再隐藏(交叉淡入淡出)。 */ private _updateWallFountainDisplay() { const battle = gg.game?.CurentBattle; const wallTarget1 = find('目标点/wallTarget1', this.node); if (!battle || !wallTarget1?.isValid) return; const maxHp = Math.max(1, battle.WallMaxHp); const ratio = battle.CurentWallHp / maxHp; let tier = 3; if (ratio >= 0.75) tier = 0; else if (ratio >= 0.5) tier = 1; else if (ratio >= 0.25) tier = 2; const names = ['喷泉', '喷泉2', '喷泉3', '喷泉4']; const newNode = find(names[tier], wallTarget1); // 节点尚未挂好时不写 _lastFountainTier,避免「假同步」后永远不再刷新(偶现喷泉不显示) if (!newNode?.isValid) return; const duration = 2; // 首次进入战斗 / 重置后:直接按档位点亮,避免与其它初始化时序竞态 if (this._lastFountainTier < 0 || this._lastFountainTier > 3) { for (const name of names) { const n = find(name, wallTarget1); if (n?.isValid && n !== newNode) { Tween.stopAllByTarget(n); n.active = false; n.opacity = 0; } } Tween.stopAllByTarget(newNode); newNode.active = true; newNode.opacity = 255; this._lastFountainTier = tier; return; } // 档位不变:若当前档喷泉被误隐藏或透明度异常(tween 被 stop、异步回调顺序等),补一次淡入 if (tier === this._lastFountainTier) { if (newNode.active && newNode.opacity >= 64) return; newNode.active = true; Tween.stopAllByTarget(newNode); const from = newNode.opacity < 1 ? 0 : Math.min(newNode.opacity, 200); newNode.opacity = from; tween(newNode).to(0.35, { opacity: 255 }, { easing: 'quadOut' }).start(); return; } const oldNode = find(names[this._lastFountainTier], wallTarget1); if (oldNode?.isValid) { Tween.stopAllByTarget(oldNode); tween(oldNode).to(duration, { opacity: 0 }, { easing: 'quadIn' }).call(() => { if (oldNode?.isValid) oldNode.active = false; }).start(); } newNode.active = true; newNode.opacity = 100; Tween.stopAllByTarget(newNode); tween(newNode).to(duration, { opacity: 255 }, { easing: 'quadOut' }).start(); this._lastFountainTier = tier; } //美女受击动画 showMeinvBeHitEffect() { const wallTarget1 = find('目标点/wallTarget1', this.node); if(!wallTarget1 || !wallTarget1.isValid){ return; } let meinv = wallTarget1.getChildByName('美女'); if(meinv?.isValid && this.meinvAnimState != '受击'){ this.meinvAnimState = '受击'; meinv.getComponent(sp.Skeleton).setAnimation(0, '受击', true) } } _onPlayerHit(){ this.showMeinvBeHitEffect(); if(this.timeHit){ clearTimeout(this.timeHit); } // 喷泉状态:随城墙血量分档淡入淡出(受击时刷新) this._updateWallFountainDisplay(); this.timeHit = setTimeout(() => { this.showMeinvIdleEffect(); }, 2000); } }