showStack(duration, stackCount, fanToLeft, stackLabelOffset, fanScale) {
    if (duration == null) { duration = CONFIG.ANIMATE_FAST_DURATION; }
    if (stackCount == null) { stackCount = 2; }
    if (stackLabelOffset == null) { stackLabelOffset = cc.p(0, 0); }
    if (fanScale == null) { fanScale = 5; }

    const contentSize = this.getContentSize();
    const centerPosition = this.getCenterPosition();

    if (this.sdkCard != null) {
      return new Promise((resolve, reject) => {
        // wait for resources
        this.whenResourcesReady(this.getCardResourceRequestId()).then((cardResourceRequestId) => {
          if (!this.getAreResourcesValid(cardResourceRequestId)) return; // card has changed

          // create card stack sprites
          for (var i = this._cardStackSprites.length; i < stackCount; i++) {
            var cardStackSprite = BaseSprite.create(this.getCardBackgroundSpriteIdentifier());
            cardStackSprite.setLeveled(true);
            cardStackSprite.setLevelsOutWhite(255 - (i + 1) * 75);
            this.addChild(cardStackSprite, -10 - i);
            this._cardStackSprites.push(cardStackSprite);
          }

          // create label
          if (this._cardStackLabel == null) {
            this._cardStackLabel = new cc.LabelTTF(`X${stackCount + 1}`, RSX.font_bold.name, 14, cc.size(100, 30), cc.TEXT_ALIGNMENT_CENTER);
            this._cardStackLabel.setFontFillColor(cc.color(200, 200, 200, 255));
            this._cardStackLabel.enableStroke(cc.color(0, 0, 0, 255), 2, false);
            this._cardStackLabel.setPosition(centerPosition.x - contentSize.width * 0.5 + stackLabelOffset.x, this.getCardBottom() - contentSize.height * 0.5 + stackLabelOffset.y);
            this._containerNodeFront.addChild(this._cardStackLabel, this.cardBackgroundSprite.getLocalZOrder() + 1.0);
          }

          // animate out stack
          for (var i = 0; i < stackCount; i++) {
            var cardStackSprite = this._cardStackSprites[i];
            cardStackSprite.setVisible(true);
            cardStackSprite.setPosition(centerPosition);
            const cardStackPosition = cc.p(
              centerPosition.x + (fanToLeft ? -fanScale : fanScale) * (i + 1),
              centerPosition.y - fanScale * (i + 1),
            );
            cardStackSprite.setRotation(0.0);
            const cardStackRotation = (fanToLeft ? -fanScale : fanScale) * (i + 1);
            cardStackSprite.runAction(
              cc.spawn(
                cc.moveTo(duration, cardStackPosition).easing(cc.easeCubicActionOut()),
                cc.rotateTo(duration, cardStackRotation).easing(cc.easeCubicActionOut()),
              ),
            );
          }

          // delay, show label, then resolve
          this._cardStackLabel.setOpacity(0);
          this._cardStackLabel.setVisible(true);
          this._cardStackLabel.runAction(cc.sequence(
            cc.delayTime(duration),
            cc.fadeIn(CONFIG.ANIMATE_FAST_DURATION),
            cc.callFunc(resolve),
          ));
        });
      });
    }
  }
Shows a stack of fake cards behind this one with a count label, and returns a promise.
@param {Number} [duration=CONFIG.ANIMATE_FAST_DURATION]
@param {Number} [stackCount=2]
@param {Boolean} [fanToLeft=false]
@returns {Promise}