ctor(sdkPlayer) {
    if (sdkPlayer == null) {
      throw new Error('GeneralSpeechNode must be initialized with a player!');
    }
    this._sdkPlayer = sdkPlayer;

    this._super();

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

      // create bg sprite
      this.bgSpriteGlow = new FXRipplingGlowImageMapSprite({
        spriteIdentifier: RSX.dialog_plate_glow.img,
        // blendSrc: "SRC_ALPHA",
        // blendDst: "ONE",
        scale: 1.0,
        levelsInWhite: 200,
        // gamma: 2.0,
        gamma: 0.75,
        intensity: 0.75,
      });
      this.bgSpriteGlow.setPosition(-95, -6);
      this.addChild(this.bgSpriteGlow, -1);

      // create bg sprite
      this.bgSprite = new BaseSprite(RSX.dialog_plate.img);
      this.addChild(this.bgSprite, 0);

      // get the general for this player
      const playerId = this._sdkPlayer.getPlayerId();
      const playerSetupData = SDK.GameSession.getInstance().getPlayerSetupDataForPlayerId(playerId);
      const originalGeneral = SDK.GameSession.getCardCaches().getCardById(playerSetupData.generalId);
      const general = SDK.GameSession.getInstance().getGeneralForPlayerId(playerId) || originalGeneral;
      const portraitCenterPosition = cc.p(-159, 0);

      const generalSpeechResource = general.getSpeechResource() || originalGeneral.getSpeechResource();
      this.generalSprite = new BaseSprite(generalSpeechResource.img);
      this.generalSprite.setAntiAlias(false);
      this.generalSprite.setPosition(portraitCenterPosition);
      this.addChild(this.generalSprite, 1);

      this.generalBorderSprite = new BaseSprite(RSX.dialogue_border.img);
      this.generalBorderSprite.setAntiAlias(false);
      this.generalBorderSprite.setPosition(portraitCenterPosition);

      // create carat sprite
      this._proceedCarrotSprite = GlowSprite.create(RSX.dialogue_carat.img);
      this._proceedCarrotSprite.setAntiAlias(false);
      this._proceedCarrotSprite.setAnchorPoint(1, 0);
      this._proceedCarrotSprite.setPosition(175, -55);
      this._proceedCarrotSprite.setVisible(false);
      this._proceedCarrotSprite.setGlowNoiseExpandModifier(100);
      this._proceedCarrotSprite.setGlowThickness(1);
      this._proceedCarrotSprite.setGlowMinAlpha(0);
      this._proceedCarrotSprite.setGlowMaxAlpha(255);
      this._proceedCarrotSprite.setGlowFrequency(CONFIG.INSTRUCTIONAL_CARROT_GLOW_FREQUENCY);
      this._proceedCarrotSprite.showGlowForPlayer();
      this._proceedCarrotSprite.setGlowMaxAlpha(255);
      this._proceedCarrotSprite.setGlowVerticalFadeFromTop(1.0);
      this._proceedCarrotSprite.setGlowing(false);
      this.addChild(this._proceedCarrotSprite, 0);

      // speaker label
      this.speakerLabel = new cc.LabelTTF('', RSX.font_bold.name, 16, cc.size(CONFIG.GENERAL_SPEECH_WIDTH, 0.0));
      this.speakerLabel.setAnchorPoint(0, 1);
      this.speakerLabel.setFontFillColor(CONFIG.DIALOGUE_HEADER_TITLE_COLOR);
      this.speakerLabel.setString(general.getName(), true);
      this.speakerLabel.setPositionX(Math.round(this.bgSprite.width * -0.13));
      this.addChild(this.speakerLabel, 1);

      this._updateLayout();
    });

    return true;
  }
*************************************************************************
 GeneralSpeechNode
 - node used to show a general's speech
**************************************************************************