Пример #1
0
/**
 * @brief Notifies this entity that it has just attacked an enemy.
 *
 * This function is called even if this attack was not successful.
 *
 * @param attack the attack
 * @param victim the enemy just hurt
 * @param result indicates how the enemy has reacted to the attack
 * @param killed indicates that the attack has just killed the enemy
 */
void CarriedItem::notify_attacked_enemy(EnemyAttack attack, Enemy& victim,
    EnemyReaction::Reaction& result, bool killed) {

  if (result.type != EnemyReaction::IGNORED) {
    break_item();
  }
}
Пример #2
0
/**
 * \brief This function is called when a crystal detects a collision with this entity.
 * \param crystal the crystal
 * \param collision_mode the collision mode that detected the event
 */
void CarriedItem::notify_collision_with_crystal(Crystal& crystal, CollisionMode collision_mode) {

  if (collision_mode == COLLISION_OVERLAPPING
      && is_being_thrown()
      && !can_explode()) {

    crystal.activate(*this);
    break_item();
  }
}
Пример #3
0
/**
 * \brief This function is called when a switch detects a collision with this entity.
 * \param sw the switch
 * \param collision_mode the collision mode that detected the event
 */
void CarriedItem::notify_collision_with_switch(Switch& sw, CollisionMode collision_mode) {

  if (collision_mode == COLLISION_OVERLAPPING
      && is_being_thrown()
      && !can_explode()) {

    sw.try_activate();
    break_item();
  }
}
Пример #4
0
/**
 * \brief Destroys the item after it finishes its thrown movement.
 *
 * How the item breaks depends on the ground where it lands.
 */
void CarriedItem::break_item_on_ground() {

  get_movement()->stop();

  Ground ground = get_ground_below();
  switch (ground) {

    case Ground::EMPTY:
      // Nothing here: fall one layer below.
    {
      int layer = get_layer();
      if (layer == 0) {
        // Cannot fall lower.
        break_item();
      }
      else {
        get_entities().set_entity_layer(*this, layer - 1);
        break_item_on_ground();  // Do this again on the next layer.
      }
      break;
    }

    case Ground::HOLE:
      Sound::play("jump");
      remove_from_map();
      break;

    case Ground::DEEP_WATER:
    case Ground::LAVA:
      Sound::play("walk_on_water");
      remove_from_map();
      break;

    default:
      // Break the item normally.
      break_item();
      break;
  }

  is_throwing = false;
  is_breaking = true;
}
Пример #5
0
/**
 * \copydoc Entity::notify_attacked_enemy
 */
void CarriedItem::notify_attacked_enemy(
    EnemyAttack /* attack */,
    Enemy& /* victim */,
    const Sprite* /* victim_sprite */,
    EnemyReaction::Reaction& result,
    bool /* killed */) {

  if (result.type != EnemyReaction::ReactionType::IGNORED) {
    break_item();
  }
}
Пример #6
0
/**
 * \brief Notifies this entity that it has just failed to change its position
 * because of obstacles.
 */
void CarriedItem::notify_obstacle_reached() {

  if (is_throwing && !is_broken()) {
    break_item();
  }
}
Пример #7
0
/**
 * \brief This function is called repeatedly.
 */
void CarriedItem::update() {

  // update the sprite and the position
  Entity::update();

  if (is_suspended()) {
    return;
  }

  // when the hero finishes lifting the item, start carrying it
  if (is_lifting && get_movement()->is_finished()) {
    is_lifting = false;

    // make the item follow the hero
    clear_movement();
    set_movement(std::make_shared<RelativeMovement>(
        std::static_pointer_cast<Hero>(hero.shared_from_this()),
        0,
        -18,
        true
    ));
  }

  // when the item has finished flying, destroy it
  else if (can_explode() && !is_breaking) {

    uint32_t now = System::now();

    if (now >= explosion_date) {
      break_item();
    }
    else if (will_explode_soon()) {

      std::string animation = get_sprite().get_current_animation();
      if (animation == "stopped") {
        get_sprite().set_current_animation("stopped_explosion_soon");
      }
      else if (animation == "walking") {
        get_sprite().set_current_animation("walking_explosion_soon");
      }
    }
  }

  if (is_broken()) {
    remove_from_map();
  }
  else if (is_throwing) {
    shadow_sprite->update();

    if (break_one_layer_above) {
      break_item();
      int layer = get_layer();
      if (layer != get_map().get_highest_layer()) {
        get_entities().set_entity_layer(*this, layer + 1);
      }
      break_one_layer_above = false;
    }
    else if (get_movement()->is_stopped() || y_increment >= 7) {
      // Interrupt the movement.
      break_item_on_ground();
    }
    else {
      uint32_t now = System::now();
      while (now >= next_down_date) {
        next_down_date += 40;
        item_height -= y_increment;
        y_increment++;
      }
    }
  }
}
Пример #8
0
/**
 * @brief This function is called repeatedly.
 */
void CarriedItem::update() {

  // update the sprite and the position
  MapEntity::update();

  if (suspended) {
    return;
  }

  // when the hero finishes lifting the item, start carrying it
  if (is_lifting && get_movement()->is_finished()) {
    is_lifting = false;

    // make the item follow the hero
    clear_movement();
    set_movement(new FollowMovement(&hero, 0, -18, true));
  }

  // when the item has finished flying, destroy it
  else if (can_explode() && !is_breaking) {
    
    uint32_t now = System::now();
    
    if (now >= explosion_date) {
      break_item();
    }
    else if (will_explode_soon()) {

      std::string animation = get_sprite().get_current_animation();
      if (animation == "stopped") {
        get_sprite().set_current_animation("stopped_explosion_soon");
      }
      else if (animation == "walking") {
        get_sprite().set_current_animation("walking_explosion_soon");
      }
    }
  }

  if (is_throwing) {
    shadow_sprite->update();

    if (is_broken()) {
      remove_from_map();
    }
    else if (break_on_intermediate_layer) {
      break_item();
      get_entities().set_entity_layer(*this, LAYER_INTERMEDIATE);
      break_on_intermediate_layer = false;
    }
    else if (get_movement()->is_stopped() || y_increment >= 7) {
      break_item();
    }
    else {
      uint32_t now = System::now();
      while (now >= next_down_date) {
        next_down_date += 40;
        item_height -= y_increment;
        y_increment++;
      }
    }
  }
}