showOpeningAndRewards() {
    return this.whenRequiredResourcesReady().then((requestId) => {
      if (!this.getAreResourcesValid(requestId)) return; // load invalidated or resources changed

      this._rewardZodiacs = [];

      return new Promise((resolve, reject) => {
        // show crate as static but preserve fx
        this.showStaticState(CONFIG.FADE_FAST_DURATION, true);

        // play explosion sfx
        audio_engine.current().play_effect(RSX.sfx_loot_crate_explode.audio, false);

        const uleg = 0.70710678118; // unit triangle leg length
        const pieceTravelDistance = 250; // Distance for exploding out loot crate pieces
        const centerPosition = this.getCenterPosition();

        const locResolve = resolve;
        this.runAction(cc.sequence(
          // cc.delayTime(1),// To sync with audio
          cc.callFunc(() => {
            // wipe flare
            const wipeFlare = FXFbmPolarFlareWipeSprite.create();
            wipeFlare.setBlendFunc(cc.SRC_ALPHA, cc.ONE);
            wipeFlare.setTextureRect(cc.rect(0, 0, 512, 512));
            wipeFlare.setAnchorPoint(0.5, 0.5);
            wipeFlare.setPosition(centerPosition);
            wipeFlare.setColor(cc.color(165, 233, 255));
            this.addChild(wipeFlare, this._zOrderInfrontOfCrate);

            // run the wipe effect
            wipeFlare.runAction(cc.sequence(
              cc.fadeIn(0.01),
              cc.actionTween(0.25, 'phase', 0.0, 0.5),
              cc.actionTween(0.75, 'phase', 0.5, 1.5),
              cc.fadeOut(0.1),
              cc.removeSelf(),
            ));
          }),

          cc.spawn(
            // Break apart loot crate pieces
            cc.targetedAction(this._lootCrateBackLeftSprite, cc.spawn(
              cc.moveBy(CONFIG.MOVE_SLOW_DURATION, {
                x: -uleg * pieceTravelDistance,
                y: uleg * pieceTravelDistance,
              }).easing(cc.easeExponentialOut()),
              cc.scaleTo(CONFIG.MOVE_SLOW_DURATION, 0.8).easing(cc.easeExponentialOut()),
              cc.sequence(
                cc.delayTime(CONFIG.MOVE_SLOW_DURATION * 0.7),
                cc.fadeOut(CONFIG.MOVE_SLOW_DURATION * 0.3),
              ),
            )),
            cc.targetedAction(this._lootCrateBackRightSprite, cc.spawn(
              cc.moveBy(CONFIG.MOVE_SLOW_DURATION, {
                x: uleg * pieceTravelDistance,
                y: uleg * pieceTravelDistance,
              }).easing(cc.easeExponentialOut()),
              cc.scaleTo(CONFIG.MOVE_SLOW_DURATION, 0.8).easing(cc.easeExponentialOut()),
              cc.sequence(
                cc.delayTime(CONFIG.MOVE_SLOW_DURATION * 0.7),
                cc.fadeOut(CONFIG.MOVE_SLOW_DURATION * 0.3),
              ),
            )),
            cc.targetedAction(this._lootCrateTopSprite, cc.spawn(
              cc.moveBy(CONFIG.MOVE_SLOW_DURATION, {
                x: 0,
                y: pieceTravelDistance,
              }).easing(cc.easeExponentialOut()),
              cc.scaleTo(CONFIG.MOVE_SLOW_DURATION, 0.9).easing(cc.easeExponentialOut()),
              cc.sequence(
                cc.delayTime(CONFIG.MOVE_SLOW_DURATION * 0.7),
                cc.fadeOut(CONFIG.MOVE_SLOW_DURATION * 0.3),
              ),
            )),
            cc.targetedAction(this._lootCrateBottomSprite, cc.spawn(
              cc.moveBy(CONFIG.MOVE_SLOW_DURATION, {
                x: 0,
                y: -pieceTravelDistance,
              }).easing(cc.easeExponentialOut()),
              cc.scaleTo(CONFIG.MOVE_SLOW_DURATION, 1.1).easing(cc.easeExponentialOut()),
              cc.sequence(
                cc.delayTime(CONFIG.MOVE_SLOW_DURATION * 0.7),
                cc.fadeOut(CONFIG.MOVE_SLOW_DURATION * 0.3),
              ),
            )),
            cc.targetedAction(this._lootCrateFrontLeftSprite, cc.spawn(
              cc.moveBy(CONFIG.MOVE_SLOW_DURATION, {
                x: -uleg * pieceTravelDistance,
                y: -uleg * pieceTravelDistance,
              }).easing(cc.easeExponentialOut()),
              cc.scaleTo(CONFIG.MOVE_SLOW_DURATION, 1.2).easing(cc.easeExponentialOut()),
              cc.sequence(
                cc.delayTime(CONFIG.MOVE_SLOW_DURATION * 0.7),
                cc.fadeOut(CONFIG.MOVE_SLOW_DURATION * 0.3),
              ),
            )),
            cc.targetedAction(this._lootCrateFrontRightSprite, cc.spawn(
              cc.moveBy(CONFIG.MOVE_SLOW_DURATION, {
                x: uleg * pieceTravelDistance,
                y: -uleg * pieceTravelDistance,
              }).easing(cc.easeExponentialOut()),
              cc.scaleTo(CONFIG.MOVE_SLOW_DURATION, 1.2).easing(cc.easeExponentialOut()),
              cc.sequence(
                cc.delayTime(CONFIG.MOVE_SLOW_DURATION * 0.7),
                cc.fadeOut(CONFIG.MOVE_SLOW_DURATION * 0.3),
              ),
            )),
            cc.callFunc(() => {
              // Add explosion particles behind loot crate
              const explosionParticles = BaseParticleSystem.create(RSX.explosion.plist);
              explosionParticles.setPosition(centerPosition);
              explosionParticles.setAnchorPoint(cc.p(0.5, 0.5));
              explosionParticles.setAutoRemoveOnFinish(true);
              this.addChild(explosionParticles, this._zOrderInfrontOfCrate);

              // Remove fx from behind sphere
              this._idleParticles.stopSystem();
              this._idleParticles2.stopSystem();
              this._flareBehindCrate.runAction(cc.sequence(
                cc.fadeOut(0.2),
                cc.removeSelf(),
              ));

              // shake sphere
              this._lootCrateSphereSprite.runAction(
                Shake.create(CONFIG.MOVE_SLOW_DURATION + CONFIG.ANIMATE_MEDIUM_DURATION, 5.0, this._lootCrateSphereSprite.getPosition()),
              );
            }),
          ),

          cc.spawn(
            // animate out the sphere
            cc.targetedAction(this._lootCrateSphereSprite, cc.spawn(
              cc.fadeOut(CONFIG.ANIMATE_MEDIUM_DURATION),
              cc.scaleTo(CONFIG.ANIMATE_MEDIUM_DURATION, 0.8).easing(cc.easeBackIn()),
            )),

            // explode and animate flare out
            cc.targetedAction(this.flare, cc.sequence(
              cc.show(),
              cc.scaleTo(0.8, 8.0),
              cc.actionTween(0.8, 'armLength', 0.0, 1.0),
              cc.fadeOut(CONFIG.ANIMATE_FAST_DURATION),
            )),

            // show rewards
            cc.callFunc(() => {
              for (let i = 0; i < this._rewardNodes.length; i++) {
                this._rewardNodes[i].setPosition(this._rewardTargetPositions[i]);
              }

              this._showRewardDiscs()
                .then(() =>
                // Run through the promise chain for each reward show animation
                  _.reduce(this._rewardAnimationPromiseCallbacks, (currentPromiseCallback, nextPromiseCallback, index) => {
                    const zodiacDestroyPromiseCallback = function () {
                      return new Promise(function (index, resolve, reject) {
                        this._rewardZodiacs[index].destroy();
                        resolve();
                      }.bind(this, index));
                    }.bind(this);

                    return currentPromiseCallback.then(zodiacDestroyPromiseCallback).then(nextPromiseCallback);
                  }, Promise.resolve()).then(() => {
                    locResolve();
                  }));
            }),
          ),
          cc.delayTime(CONFIG.ANIMATE_FAST_DURATION),
        ));
      })
        .catch((error) => { EventBus.getInstance().trigger(EVENTS.error, error); });
    });
  }
Animates opening the loot crate and showing rewards.
@public
@return {Promise}