import { _decorator, AudioClip, Component, Label, Node, sp, Sprite, SpriteFrame, tween, Vec3 } from 'cc'; import GachaBase from '../Base/GachaBase'; import SpineAnimationHandler, { SocketPath, SpineAnimation, SpineSkin } from '../Base/SpineAnimationHandler'; import AudioManager from '../Manager/AudioManager'; import GachaManager, { RewardConfig } from '../Manager/GachaManager'; import Utils from '../Utilities'; const { ccclass, property } = _decorator; class RewardCard { public socket: sp.SpineSocket; public node: Node; public reward: RewardConfig; constructor(node: Node, reward: RewardConfig) { this.node = node; this.reward = reward; } public setActive(value: boolean) { this.node.setActive(value); } } @ccclass('LuckyChain') export default class LuckyChain extends GachaBase { @property(SpineAnimationHandler) private animationHandler: SpineAnimationHandler; @property(Node) private spriteRoot: Node; @property(Node) private cards: Node[] = []; @property(Sprite) private sprites: Sprite[] = []; @property({ type: SocketPath }) private cardSlotPath: SocketPath[] = []; @property(AudioClip) private sounds: AudioClip[] = []; private _activeCards: RewardCard[] = []; private _allCards: RewardCard[] = []; private _reward: RewardCard; onFocusInEditor(): void { this.animationHandler.setPropertySocketPath(this, 'cardSlotPath'); } protected onLoad(): void { this.setReward(); for (let i = 0; i < 4; i++) { const card = this._allCards.shift(); const path = this.cardSlotPath[i]; const socket = this.animationHandler.addSocket(path, card.node); card.socket = socket; this._activeCards.push(card); } this.animationHandler.setListener((_, e) => { switch (e.data.name) { case 'card-appear': AudioManager.playSfx(this.sounds[0]); this._activeCards.forEach((card) => { card.setActive(true); }); break; case 'card-claimed': AudioManager.playSfx(this.sounds[1]); const cardRemove = this._activeCards.shift(); this._reward = cardRemove; this.animationHandler.removeSocket(cardRemove.socket); cardRemove.setActive(false); cardRemove.socket = null; this._allCards.push(cardRemove); break; case 'new-card-spawned': AudioManager.playSfx(this.sounds[2]); const card = this._allCards.shift(); const path = this.cardSlotPath[this.cardSlotPath.length - 1]; const socket = this.animationHandler.addSocket(path, card.node); card.setActive(true); card.socket = socket; this._activeCards.push(card); break; } }); } protected onEnable(): void { this.spriteRoot.setActive(false); this._activeCards.forEach((card) => { card.setActive(false); }); } private setReward() { this._allCards = this.cards.map((card, i) => { const rw = GachaManager.instance.getRandomReward(); this.sprites[i].spriteFrame = rw.icon; card.getComponentInChildren(Label).string = 'x' + rw.quantity; card.setActive(false); return new RewardCard(card, rw); }); } public async show(): Promise { this.spriteRoot.setActive(true); await this.animationHandler.setAnimationAsync('appear'); await this.animationHandler.addAnimationAsync('active'); GachaManager.instance.showFloatingText( this._reward.reward.quantity.toString(), this.node.worldPosition, this._reward.reward.icon, ); GachaManager.instance.setReward(this._reward.reward.id); await Utils.delay(1.5); //update socket path for (let i = 0; i < 4; i++) { const card = this._activeCards[i]; const path = this.cardSlotPath[i]; this._activeCards[i].socket = this.animationHandler.updateSocketPath(card.socket, path); } } }