예제 #1
0
파일: Npc.cpp 프로젝트: Maxs1789/solarus
/**
 * \brief This function is called when the entity has just moved.
 *
 * If it is an NPC, its sprite's direction is updated.
 */
void Npc::notify_position_changed() {

  Entity::notify_position_changed();

  if (subtype == USUAL_NPC) {

    const SpritePtr& sprite = get_sprite();
    if (get_movement() != nullptr) {
      // The NPC is moving.
      if (sprite != nullptr) {
        if (sprite->get_current_animation() != "walking") {
          sprite->set_current_animation("walking");
        }
        int direction4 = get_movement()->get_displayed_direction4();
        sprite->set_current_direction(direction4);
      }
    }

    if (get_hero().get_facing_entity() == this &&
        get_commands_effects().get_action_key_effect() == CommandsEffects::ACTION_KEY_SPEAK &&
        !get_hero().is_facing_point_in(get_bounding_box())) {

      get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_NONE);
    }
  }
}
예제 #2
0
파일: Npc.cpp 프로젝트: Maxs1789/solarus
/**
 * \brief This function is called by the engine when there is a collision with another entity.
 *
 * If the entity is the hero, we allow him to interact with this entity.
 *
 * \param entity_overlapping the entity overlapping the detector
 * \param collision_mode the collision mode that detected the collision
 */
void Npc::notify_collision(Entity& entity_overlapping, CollisionMode collision_mode) {

  if (collision_mode == COLLISION_FACING && entity_overlapping.is_hero()) {

    Hero& hero = static_cast<Hero&>(entity_overlapping);

    if (get_commands_effects().get_action_key_effect() == CommandsEffects::ACTION_KEY_NONE
        && hero.is_free()) {

      if (subtype == USUAL_NPC // the hero can talk to usual NPCs from any direction
          || get_direction() == -1
          || hero.is_facing_direction4((get_direction() + 2) % 4)) {

        // show the appropriate action icon
        get_commands_effects().set_action_key_effect(subtype == USUAL_NPC ?
            CommandsEffects::ACTION_KEY_SPEAK : CommandsEffects::ACTION_KEY_LOOK);
      }
      else if (can_be_lifted() && get_equipment().has_ability(Ability::LIFT)) {
        get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_LIFT);
      }
    }
  }
  else if (collision_mode == COLLISION_OVERLAPPING && entity_overlapping.get_type() == EntityType::FIRE) {

    if (behavior == BEHAVIOR_ITEM_SCRIPT) {
      EquipmentItem& item = get_equipment().get_item(item_name);
      get_lua_context()->item_on_npc_collision_fire(item, *this);
    }
    else {
      get_lua_context()->npc_on_collision_fire(*this);
    }
  }
}
예제 #3
0
파일: Bomb.cpp 프로젝트: Maxs1789/solarus
/**
 * \brief This function is called when the entity has just moved.
 */
void Bomb::notify_position_changed() {

  Entity::notify_position_changed();

  if (get_hero().get_facing_entity() == this
      && get_commands_effects().get_action_key_effect() == CommandsEffects::ACTION_KEY_LIFT
      && !get_hero().is_facing_point_in(get_bounding_box())) {

    get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_NONE);
  }
}
예제 #4
0
파일: Npc.cpp 프로젝트: Maxs1789/solarus
/**
 * \copydoc Entity::notify_action_command_pressed
 */
bool Npc::notify_action_command_pressed() {

  Hero& hero = get_hero();
  if (hero.is_free() &&
      get_commands_effects().get_action_key_effect() != CommandsEffects::ACTION_KEY_NONE
  ) {

    CommandsEffects::ActionKeyEffect effect = get_commands_effects().get_action_key_effect();
    get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_NONE);

    SpritePtr sprite = get_sprite();

    // if this is a usual NPC, look towards the hero
    if (subtype == USUAL_NPC) {
      int direction = (get_hero().get_animation_direction() + 2) % 4;
      if (sprite != nullptr) {
        sprite->set_current_direction(direction);
      }
    }

    if (effect != CommandsEffects::ACTION_KEY_LIFT) {
      // start the normal behavior
      if (behavior == BEHAVIOR_DIALOG) {
        get_game().start_dialog(dialog_to_show, ScopedLuaRef(), ScopedLuaRef());
      }
      else {
        call_script_hero_interaction();
      }
      return true;
    }
    else {
      // lift the entity
      if (get_equipment().has_ability(Ability::LIFT)) {

        std::string animation_set_id = "stopped";
        if (sprite != nullptr) {
          animation_set_id = sprite->get_animation_set_id();
        }
        hero.start_lifting(std::make_shared<CarriedObject>(
            hero,
            *this,
            animation_set_id,
            "stone",
            2,
            0)
        );
        Sound::play("lift");
        remove_from_map();
        return true;
      }
    }
  }
  return false;
}
예제 #5
0
파일: Block.cpp 프로젝트: Maxs1789/solarus
/**
 * \copydoc Entity::notify_action_command_pressed
 */
bool Block::notify_action_command_pressed() {

  if (get_commands_effects().get_action_key_effect() == CommandsEffects::ACTION_KEY_GRAB) {
    get_hero().start_grabbing();
    return true;
  }

  return false;
}
예제 #6
0
/**
 * \brief Starts this state.
 * \param previous_state the previous state
 */
void Hero::LiftingState::start(const State* previous_state) {

  State::start(previous_state);

  // initialize the entity that will be lifted
  lifted_item->set_map(get_map());

  get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_THROW);
  get_sprites().set_animation_lifting();
  get_sprites().set_lifted_item(lifted_item);
  get_entity().set_facing_entity(nullptr);

  get_equipment().notify_ability_used(Ability::LIFT);
}
예제 #7
0
/**
 * \brief Starts this state.
 * \param previous_state the previous state
 */
void Hero::StairsState::start(const State* previous_state) {

    State::start(previous_state);

    // movement
    int speed = stairs->is_inside_floor() ? 40 : 24;
    std::string path = stairs->get_path(way);
    std::shared_ptr<PathMovement> movement = std::make_shared<PathMovement>(
                path, speed, false, true, false
            );

    // sprites and sound
    HeroSprites& sprites = get_sprites();
    if (carried_item == nullptr) {
        sprites.set_animation_walking_normal();
    }
    else {
        sprites.set_lifted_item(carried_item);
        sprites.set_animation_walking_carrying();
    }
    sprites.set_animation_direction((path[0] - '0') / 2);
    get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_NONE);

    Hero& hero = get_entity();
    if (stairs->is_inside_floor()) {
        if (way == Stairs::NORMAL_WAY) {
            // Toward a higher layer: change the layer now.
            int layer = stairs->get_layer();
            Debug::check_assertion(layer < get_map().get_num_layers(), "Invalid stairs layer");
            get_entities().set_entity_layer(hero, layer + 1);
        }
    }
    else {
        sprites.set_clipping_rectangle(stairs->get_clipping_rectangle(way));
        if (way == Stairs::REVERSE_WAY) {
            Point dxy = movement->get_xy_change();
            int fix_y = 8;
            if (path[path.size() - 1] == '2') {
                fix_y *= -1;
            }
            hero.set_xy(hero.get_x() - dxy.x, hero.get_y() - dxy.y + fix_y);
        }
    }
    hero.set_movement(movement);
}
예제 #8
0
파일: Bomb.cpp 프로젝트: Maxs1789/solarus
/**
 * \copydoc Entity::notify_action_command_pressed
 */
bool Bomb::notify_action_command_pressed() {

  CommandsEffects::ActionKeyEffect effect = get_commands_effects().get_action_key_effect();

  if (effect == CommandsEffects::ACTION_KEY_LIFT
      && get_hero().get_facing_entity() == this
      && get_hero().is_facing_point_in(get_bounding_box())) {

    get_hero().start_lifting(std::make_shared<CarriedObject>(
        get_hero(),
        *this,
        "entities/bomb",
        "",
        0,
        explosion_date)
    );
    Sound::play("lift");
    remove_from_map();
    return true;
  }

  return false;
}
예제 #9
0
/**
 * \brief Ends this state.
 * \param next_state the next state
 */
void Hero::LiftingState::stop(const State* next_state) {

  State::stop(next_state);

  if (lifted_item != nullptr) {

    get_sprites().set_lifted_item(nullptr);

    // the lifted item is still managed by this state
    switch (next_state->get_previous_carried_item_behavior()) {

    case CarriedItem::BEHAVIOR_THROW:
      throw_item();
      break;

    case CarriedItem::BEHAVIOR_DESTROY:
    case CarriedItem::BEHAVIOR_KEEP:
      lifted_item = nullptr;
      break;
    }
    get_commands_effects().set_action_key_effect(CommandsEffects::ACTION_KEY_NONE);
  }
}