コード例 #1
0
ファイル: DialogBoxSystem.cpp プロジェクト: stavrossk/solarus
/**
 * \brief This function is called by the game when a command is pressed
 * while a dialog is active.
 *
 * Nothing happens if the dialog is handled in Lua.
 *
 * \param command The command pressed.
 * \return \c true if the command was handled (that is, if the dialog box
 * is active and is the built-in one).
 */
bool DialogBoxSystem::notify_command_pressed(GameCommand command) {

  if (!is_enabled()) {
    return false;
  }

  if (!built_in) {
    // The dialog box is handled by a Lua script.
    return false;
  }

  if (command == GameCommand::ACTION) {
    show_more_lines();
  }
  else if (command == GameCommand::UP || command == GameCommand::DOWN) {
    if (is_question && !has_more_lines()) {
      // Switch the selected answer.
      selected_first_answer = !selected_first_answer;
      int selected_line_index = selected_first_answer ? 1 : 2;
      for (int i = 0; i < nb_visible_lines; i++) {
        line_surfaces[i]->set_text_color(Color::white);
      }
      line_surfaces[selected_line_index]->set_text_color(Color::yellow);
    }
  }

  return true;
}
コード例 #2
0
/**
 * @brief This function is called when the user presses the action key.
 */
void DialogBox::action_key_pressed() {

  if (is_full()) { // the current group of 3 lines is over
    show_more_lines();
  }
  else if (skip_mode != Dialog::SKIP_NONE) {
    show_all_now();
  }
}
コード例 #3
0
/**
 * @brief Starts a dialog.
 *
 * If there was already a dialog, it must be finished.
 *
 * @param dialog_id of the dialog
 * @param issuer_script the script that issued the request to start a dialog
 * (will be notified when the dialog finishes), or NULL
 * @param vertical_position vertical position where to display the dialog box (default: auto)
 */
void DialogBox::start_dialog(const std::string& dialog_id, Script* issuer_script,
    VerticalPosition vertical_position) {

  Debug::check_assertion(!is_enabled() || is_full(), StringConcat()
      << "Cannot start dialog '" << dialog_id
      << "': another dialog '" << this->dialog_id << "' is already started");

  bool first = !is_enabled();
  if (first) {
    // save the action and sword keys
    KeysEffect& keys_effect = game.get_keys_effect();
    action_key_effect_saved = keys_effect.get_action_key_effect();
    sword_key_effect_saved = keys_effect.get_sword_key_effect();
    this->icon_number = -1;
    this->skip_mode = Dialog::SKIP_NONE;
    this->char_delay = char_delays[SPEED_FAST];
    this->dialog_id = dialog_id;
  }

  // initialize the dialog data
  this->dialog = DialogResource::get_dialog(dialog_id);
  this->line_it = dialog.get_lines().begin();
  this->line_index = 0;
  this->char_index = 0;
  this->skipped = false;

  if (dialog.get_skip_mode() != Dialog::SKIP_UNCHANGED) {
    this->skip_mode = dialog.get_skip_mode();
  }

  if (dialog.get_icon() != -2) { // -2 means unchanged
    this->icon_number = dialog.get_icon();
  }
  if (dialog.is_question()) {
    this->last_answer = 0;
  }
  else {
    this->last_answer = -1;
  }
  question_dst_position.set_y(box_dst_position.get_y() + 27);

  if (first) {
    set_vertical_position(vertical_position);

    // notify the scripts
    game.get_map_script().event_dialog_started(dialog_id);
    this->issuer_script = issuer_script;
    if (issuer_script != NULL) {
      issuer_script->event_dialog_started(dialog_id);
    }
  }

  // start displaying text
  show_more_lines();
}
コード例 #4
0
/**
 * @brief This function is called when the user presses the sword key.
 */
void DialogBox::sword_key_pressed() {

  if (skip_mode == Dialog::SKIP_ALL) {
    skipped = true;
    close();
  }
  else if (is_full()) {
    show_more_lines();
  }
  else if (skip_mode == Dialog::SKIP_CURRENT) {
    show_all_now();
  }
}
コード例 #5
0
/**
 * @brief Stops displaying gradually the current 3 lines, shows them
 * immediately.
 * If the 3 lines were already finished, the next group of 3 lines starts
 * (if any).
 */
void DialogBox::show_all_now() {

  if (is_full()) {
    show_more_lines();
  }
  else {

    // check the end of the current line
    while (!is_full()) {

      while (!is_full() && char_index >= lines[line_index].size()) {
        char_index = 0;
        line_index++;
      }
      if (!is_full()) {
        add_character();
      }
    }
  }
}
コード例 #6
0
/**
 * \brief Opens the dialog box to show a dialog.
 *
 * No other dialog should be already running.
 *
 * \param dialog_id Id of the dialog to show.
 * \param info_ref Lua ref to an optional info parameter to pass to the
 * dialog box, or an empty ref.
 * \param callback_ref Lua ref to a function to call when the dialog finishes,
 * or an empty ref.
 */
void DialogBoxSystem::open(
    const std::string& dialog_id,
    const ScopedLuaRef& info_ref,
    const ScopedLuaRef& callback_ref
) {
  Debug::check_assertion(!is_enabled(), "A dialog is already active");

  this->dialog_id = dialog_id;
  this->dialog = DialogResource::get_dialog(dialog_id);
  this->callback_ref = callback_ref;

  // Save commands.
  KeysEffect& keys_effect = game.get_keys_effect();
  keys_effect.save_action_key_effect();
  keys_effect.set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
  keys_effect.save_sword_key_effect();
  keys_effect.set_sword_key_effect(KeysEffect::SWORD_KEY_NONE);
  keys_effect.save_pause_key_effect();
  keys_effect.set_pause_key_effect(KeysEffect::PAUSE_KEY_NONE);

  // A dialog was just started: notify Lua.
  LuaContext& lua_context = game.get_lua_context();
  lua_State* l = lua_context.get_internal_state();
  built_in = !lua_context.notify_dialog_started(
      game, dialog, info_ref
  );

  if (built_in) {

    // Show a built-in default dialog box.
    keys_effect.set_action_key_effect(KeysEffect::ACTION_KEY_NEXT);

    // Prepare the text.
    std::string text = dialog.get_text();
    this->is_question = false;

    if (dialog_id == "_shop.question") {
      // Built-in dialog with the "do you want to buy" question and the price.
      this->is_question = true;
      size_t index = text.find("$v");
      if (index != std::string::npos) {
        // Replace the special sequence '$v' by the price of the shop item.
        info_ref.push();
        int price = LuaTools::check_int(l, -1);
        lua_pop(l, -1);
        std::ostringstream oss;
        oss << price;
        text = text.replace(index, 2, oss.str());
      }
    }

    remaining_lines.clear();
    std::istringstream iss(text);
    std::string line;
    while (std::getline(iss, line)) {
      remaining_lines.push_back(line);
    }

    // Determine the position.
    const Rectangle& camera_position = game.get_current_map().get_camera_position();
    bool top = false;
    if (game.get_hero()->get_y() >= camera_position.get_y() + 130) {
      top = true;
    }
    int x = camera_position.get_width() / 2 - 110;
    int y = top ? 32 : camera_position.get_height() - 96;

    text_position = { x, y };

    // Start showing text.
    show_more_lines();
  }
}