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.
231 lines
8.5 KiB
231 lines
8.5 KiB
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() {
|
|
if (this.meinvAnimState === '胜利') return;
|
|
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() {
|
|
if (this.meinvAnimState === '胜利') return;
|
|
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(){
|
|
if (gg.game?.CurentBattle?.IsGameOver) return;
|
|
this.showMeinvBeHitEffect();
|
|
if(this.timeHit){
|
|
clearTimeout(this.timeHit);
|
|
}
|
|
|
|
// 喷泉状态:随城墙血量分档淡入淡出(受击时刷新)
|
|
this._updateWallFountainDisplay();
|
|
this.timeHit = setTimeout(() => {
|
|
this.showMeinvIdleEffect();
|
|
}, 2000);
|
|
}
|
|
}
|
|
|
|
|
|
|