showUnlockPack() {
    return new Promise((resolve, reject) => {
      // reset and set as unlocking until finished
      this._resetPack();
      this._unlocking = true;

      this.whenRequiredResourcesReady().then((requestId) => {
        if (!this.getAreResourcesValid(requestId)) return; // resources invalidated/unloaded

        const fadeDuration = 0.8;
        const winCenterPosition = UtilsEngine.getGSIWinCenterPosition();

        // assemble motion streaks
        const motionStreakRing = new MotionStreakRingNode();
        this.innerLayer.addChild(motionStreakRing);
        motionStreakRing.animate();

        // play inward line particles
        this.lines_particles = BaseParticleSystem.create(RSX.ptcl_lines_towards_ring.plist);
        this.lines_particles.setPosition(0, 0);
        this.lines_particles.setDirectionAligned(true);
        this.lines_particles.setFadeInAtLifePct(0.1);
        this.lines_particles.setFadeOutAtLifePct(0.9);
        this.lines_particles.setStartSizeVar(40);
        this.lines_particles.setStartRadius(200);
        this.lines_particles.setStartRadiusVar(50);
        this.innerLayer.addChild(this.lines_particles);

        this.inward_particles = BaseParticleSystem.create(RSX.ptcl_spiral_assemble_for_booster.plist);
        this.inward_particles.setAnchorPoint(cc.p(0.5, 0.5));
        this.inward_particles.setPosition(0, 0);
        this.innerLayer.addChild(this.inward_particles);

        // fade background
        this.vignette.stopActionByTag(CONFIG.FADE_TAG);
        const fadeAction = cc.fadeTo(fadeDuration, 200);
        fadeAction.setTag(CONFIG.FADE_TAG);
        this.vignette.runAction(fadeAction);

        // lock plates
        // this.topRedPlateBottom.setPosition(cc.p(winCenterPosition.x, winCenterPosition.y - 100))
        // this.topRedPlateBottom.setOpacity(0)
        this.topRedPlateBottom.runAction(cc.sequence(
          cc.delayTime(0.1),
          cc.spawn(
            cc.fadeIn(0.1),
            cc.moveTo(0.5, winCenterPosition).easing(cc.easeExponentialOut()),
          ),
        ));
        // this.topRedPlateLeft.setPosition(cc.p(winCenterPosition.x - 100, winCenterPosition.y + 100))
        // this.topRedPlateLeft.setOpacity(0)
        this.topRedPlateLeft.runAction(cc.sequence(
          cc.delayTime(0.2),
          cc.spawn(
            cc.fadeIn(0.1),
            cc.moveTo(0.5, winCenterPosition).easing(cc.easeExponentialOut()),
          ),
        ));
        // this.topRedPlateBottom.setOpacity(0)
        // this.topRedPlateBottom.setPosition(cc.p(winCenterPosition.x + 100, winCenterPosition.y + 100))
        this.topRedPlateRight.runAction(cc.sequence(
          cc.delayTime(0.3),
          cc.spawn(
            cc.fadeIn(0.1),
            cc.moveTo(0.5, winCenterPosition).easing(cc.easeExponentialOut()),
          ),
        ));

        // animate global tone curve using scene
        this.getScene().runAction(ToneCurve.create(fadeDuration, 0.0, 1.0));

        // delay for fade duration and then resolve
        this.runAction(cc.sequence(
          cc.delayTime(fadeDuration),
          cc.callFunc(resolve),
        ));
      });
    });
  }
Shows pack looping animation for unlock and returns a promise that resolves when all animations have played out.