Exemple #1
0
/**
 * \copydoc Detector::notify_action_command_pressed
 */
bool Chest::notify_action_command_pressed() {

  if (is_enabled() &&
      get_hero().is_free() &&
      get_keys_effect().get_action_key_effect() != KeysEffect::ACTION_KEY_NONE
  ) {

    if (can_open()) {
      Sound::play("chest_open");
      set_open(true);
      treasure_date = System::now() + 300;

      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
      get_hero().start_freezed();
    }
    else if (!get_cannot_open_dialog_id().empty()) {
      Sound::play("wrong");
      get_game().start_dialog(get_cannot_open_dialog_id(), ScopedLuaRef(), ScopedLuaRef());
    }

    return true;
  }

  return false;
}
Exemple #2
0
/**
 * \brief Notifies this state that the action command was just pressed.
 */
void Hero::FreeState::notify_action_command_pressed() {

  Hero& hero = get_hero();
  Detector* facing_entity = hero.get_facing_entity();
  bool facing_entity_interaction = false;
  if (facing_entity != nullptr) {
    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE ||
        get_keys_effect().is_action_key_acting_on_facing_entity()
    ) {

      // action on the facing entity
      facing_entity_interaction = facing_entity->notify_action_command_pressed();
    }
  }

  if (!facing_entity_interaction) {
    // The event was not handled by the facing entity.
    if (hero.is_facing_point_on_obstacle()) {

      // grab an obstacle
      hero.set_state(new GrabbingState(hero));
    }
    else if (hero.can_run()) {

      // run
      hero.start_running();
    }
  }
}
Exemple #3
0
/**
 * @brief This function is called when the entity has just moved.
 */
void Bomb::notify_position_changed() {

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

    get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
  }
}
Exemple #4
0
/**
 * @brief This function is called by the engine when an entity overlaps the shop item.
 *
 * If the entity is the hero, we allow him to buy the item.
 *
 * @param entity_overlapping the entity overlapping the detector
 * @param collision_mode the collision mode that detected the collision
 */
void ShopItem::notify_collision(MapEntity &entity_overlapping, CollisionMode collision_mode) {

  if (entity_overlapping.is_hero() && !get_game().is_suspended()) {

    Hero &hero = (Hero&) entity_overlapping;

    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
        && hero.is_free()) {

      // we show the 'look' icon
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
Exemple #5
0
/**
 * \copydoc Detector::notify_action_command_pressed
 */
bool Crystal::notify_action_command_pressed() {

    if (get_hero().is_free() &&
            get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_LOOK
       ) {
        get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);

        // start a dialog
        get_game().start_dialog("_crystal", ScopedLuaRef(), ScopedLuaRef());
        return true;
    }

    return false;
}
/**
 * \brief This function is called by the engine when an entity overlaps the shop item.
 *
 * If the entity is the hero, we allow him to buy the item.
 *
 * \param entity_overlapping the entity overlapping the detector
 * \param collision_mode the collision mode that detected the collision
 */
void ShopTreasure::notify_collision(
    MapEntity& entity_overlapping, CollisionMode /* collision_mode */) {

  if (entity_overlapping.is_hero() && !get_game().is_suspended()) {

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

    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
        && hero.is_free()) {

      // we show the 'look' icon
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
Exemple #7
0
/**
 * \brief Stops this state.
 * \param next_state the next state
 */
void Hero::CarryingState::stop(State *next_state) {

  PlayerMovementState::stop(next_state);

  get_sprites().set_lifted_item(NULL);
  get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);

  if (carried_item != NULL) {

    switch (next_state->get_previous_carried_item_behavior(*carried_item)) {

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

    case CarriedItem::BEHAVIOR_DESTROY:
      delete carried_item;
      carried_item = NULL;
      break;

    case CarriedItem::BEHAVIOR_KEEP:
      carried_item = NULL;
      break;

    default:
      Debug::die("Invalid carried item behavior");
    }
  }
}
Exemple #8
0
/**
 * \brief Notifies this state that the action command was just pressed.
 */
void Hero::CarryingState::notify_action_command_pressed() {

  if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_THROW) {
    throw_item();
    hero.set_state(new FreeState(hero));
  }
}
Exemple #9
0
/**
 * @brief Ends this state.
 * @param next_state the next state
 */
void Hero::LiftingState::stop(State *next_state) {

  State::stop(next_state);

  if (lifted_item != NULL) {

    get_sprites().set_lifted_item(NULL);

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

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

    case CarriedItem::BEHAVIOR_DESTROY:
      delete lifted_item;
      lifted_item = NULL;
      break;

    case CarriedItem::BEHAVIOR_KEEP:
      lifted_item = NULL;
      break;
    }
    get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
  }
}
Exemple #10
0
/**
 * \brief Starts this state.
 * \param previous_state the previous state
 */
void Hero::FreezedState::start(const State* previous_state) {

  State::start(previous_state);

  get_sprites().set_animation_stopped_normal();
  get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
}
Exemple #11
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 != NULL) {

    get_sprites().set_lifted_item(NULL);

    // 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:
      destroy_lifted_item();
      break;

    case CarriedItem::BEHAVIOR_KEEP:
      // The next state is now the owner and has incremented the refcount.
      Debug::check_assertion(lifted_item->get_refcount() > 1,
          "Invalid carried item refcount");
      RefCountable::unref(lifted_item);
      lifted_item = NULL;
      break;
    }
    get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
  }
}
Exemple #12
0
/**
 * \brief Stops this state.
 * \param next_state the next state
 */
void Hero::SwimmingState::stop(State* next_state) {

  PlayerMovementState::stop(next_state);

  Hero& hero = get_hero();
  hero.set_walking_speed(hero.get_normal_walking_speed());
  get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
}
Exemple #13
0
/**
 * \brief This function is called when this entity detects a collision with the hero.
 * \param hero the hero
 * \param collision_mode the collision mode that detected the collision
 */
void Destructible::notify_collision_with_hero(Hero& hero, CollisionMode /* collision_mode */) {

  if (get_weight() != -1
      && !is_being_cut
      && !is_waiting_for_regeneration()
      && !is_regenerating
      && get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
      && hero.is_free()) {

    if (get_equipment().has_ability(Ability::LIFT, get_weight())) {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LIFT);
    }
    else {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
Exemple #14
0
/**
 * \brief Starts this state.
 * \param previous_state the previous state
 */
void Hero::SwimmingState::start(State* previous_state) {

  PlayerMovementState::start(previous_state);

  get_equipment().notify_ability_used("swim");
  get_hero().set_walking_speed(get_slow_swimming_speed());
  get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_SWIM);
}
Exemple #15
0
/**
 * @brief Notifies this detector that the player is interacting with it by
 * pressing the action command.
 *
 * This function is called when the player presses the action command
 * while the hero is facing this detector, and the action command effect lets
 * him do this.
 * A dialog is shown to let the hero buy the item.
 */
void ShopItem::notify_action_command_pressed() {

  if (get_hero().is_free()
      && get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_LOOK) {

    get_dialog_box().start_dialog(dialog_id);
    is_looking_item = true;
  }
}
Exemple #16
0
/**
 * @brief This function is called when the player interacts with this entity.
 *
 * This function is called when the player presses the action key
 * while the hero is facing this detector, and the action icon lets him do this.
 */
void CrystalSwitch::action_key_pressed() {

  if (get_hero().is_free()) {
    get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);

    // start a dialog
    get_dialog_box().start_dialog("_crystal_switch");
  }
}
Exemple #17
0
/**
 * \brief This function is called when this entity detects a collision with the hero.
 * \param hero the hero
 * \param collision_mode the collision mode that detected the collision
 */
void Destructible::notify_collision_with_hero(Hero& hero, CollisionMode collision_mode) {

  if (features[subtype].can_be_lifted
      && !is_being_cut
      && !is_disabled()
      && !is_regenerating
      && get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
      && hero.is_free()) {

    int weight = features[subtype].weight;
    if (get_equipment().has_ability("lift", weight)) {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LIFT);
    }
    else {
      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
    }
  }
}
Exemple #18
0
/**
 * \brief Notifies this state that the attack command was just pressed.
 */
void Hero::State::notify_attack_command_pressed() {

  if (!hero.is_suspended()
      && get_keys_effect().get_sword_key_effect() == KeysEffect::SWORD_KEY_SWORD
      && can_start_sword()) {

    hero.set_state(new SwordSwingingState(hero));
  }
}
Exemple #19
0
/**
 * \brief Notifies this detector that the player is interacting with it by
 * pressing the action command.
 *
 * This function is called when the player presses the action command
 * while the hero is facing this detector, and the action command effect lets
 * him do this.
 */
void Crystal::notify_action_command_pressed() {

  if (get_hero().is_free()) {
    get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);

    // start a dialog
    get_game().start_dialog("_crystal", LUA_REFNIL);
  }
}
Exemple #20
0
/**
 * \brief Notifies this detector that the player is interacting with it by
 * pressing the action command.
 *
 * This function is called when the player presses the action command
 * while the hero is facing this detector, and the action command effect lets
 * him do this.
 */
void Destructible::notify_action_command_pressed() {

  KeysEffect::ActionKeyEffect effect = get_keys_effect().get_action_key_effect();

  if ((effect == KeysEffect::ACTION_KEY_LIFT || effect == KeysEffect::ACTION_KEY_LOOK)
      && features[subtype].can_be_lifted
      && !is_being_cut
      && !is_disabled()
      && !is_regenerating) {

    int weight = features[subtype].weight;

    if (get_equipment().has_ability("lift", weight)) {

      uint32_t explosion_date = can_explode() ? System::now() + 6000 : 0;
      get_hero().start_lifting(new CarriedItem(
          get_hero(),
          *this,
          get_animation_set_id(),
          get_destruction_sound_id(),
          get_damage_on_enemies(),
          explosion_date)
      );

      // play the sound
      Sound::play("lift");

      // create the pickable item
      create_pickable();

      // remove the item from the map
      if (!features[subtype].can_regenerate) {
        destruction_callback();
        remove_from_map();
      }
      else {
        // the item can actually regenerate
        play_destroy_animation();
      }
    }
    else {
      if (features[subtype].can_be_cut
          && !features[subtype].can_explode
          && !get_equipment().has_ability("sword", 1)) {
        get_game().start_dialog("_cannot_lift_should_cut", LUA_REFNIL);
      }
      else if (!get_equipment().has_ability("lift", 1)) {
        get_game().start_dialog("_cannot_lift_too_heavy", LUA_REFNIL);
      }
      else {
        get_game().start_dialog("_cannot_lift_still_too_heavy", LUA_REFNIL);
      }
    }
  }
}
Exemple #21
0
/**
 * @brief Notifies this detector that a collision was just detected with another entity.
 *
 * This function is called by the engine when there is a collision with another entity.
 *
 * @param entity_overlapping the entity overlapping the detector
 * @param collision_mode the collision mode that detected the collision
 */
void Door::notify_collision(MapEntity& entity_overlapping, CollisionMode collision_mode) {

  if (is_closed() && entity_overlapping.is_hero()) {

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

    if (get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_NONE
        && hero.is_free()) {

      if (can_open()) {
        // The action command opens the door.
        get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_OPEN);
      }
      else if (!get_cannot_open_dialog_id().empty()) {
        // The action command shows a dialog.
        get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_LOOK);
      }
    }
  }
}
Exemple #22
0
/**
 * \brief Starts this state.
 * \param previous_state the previous state
 */
void Hero::CarryingState::start(State *previous_state) {

  PlayerMovementState::start(previous_state);

  if (is_current_state()) {
    get_sprites().set_lifted_item(carried_item);

    // action icon "throw"
    get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_THROW);
  }
}
/**
 * \copydoc Detector::notify_action_command_pressed
 */
bool ShopTreasure::notify_action_command_pressed() {

  if (get_hero().is_free()
      && get_keys_effect().get_action_key_effect() == KeysEffect::ACTION_KEY_LOOK) {

    LuaContext& lua_context = get_lua_context();
    lua_context.notify_shop_treasure_interaction(*this);
    return true;
  }

  return false;
}
Exemple #24
0
/**
 * \copydoc Detector::notify_action_command_pressed
 */
bool Destructible::notify_action_command_pressed() {

  KeysEffect::ActionKeyEffect effect = get_keys_effect().get_action_key_effect();

  if ((effect == KeysEffect::ACTION_KEY_LIFT || effect == KeysEffect::ACTION_KEY_LOOK)
      && get_weight() != -1
      && !is_being_cut
      && !is_waiting_for_regeneration()
      && !is_regenerating) {

    if (get_equipment().has_ability(Ability::LIFT, get_weight())) {

      uint32_t explosion_date = get_can_explode() ? System::now() + 6000 : 0;
      get_hero().start_lifting(std::make_shared<CarriedItem>(
          get_hero(),
          *this,
          get_animation_set_id(),
          get_destruction_sound(),
          get_damage_on_enemies(),
          explosion_date)
      );

      // Play the sound.
      Sound::play("lift");

      // Create the pickable treasure.
      create_treasure();

      if (!get_can_regenerate()) {
        // Remove this destructible from the map.
        remove_from_map();
      }
      else {
        // The item can actually regenerate.
        play_destroy_animation();
      }

      // Notify Lua.
      get_lua_context().destructible_on_lifting(*this);
    }
    else {
      // Cannot lift the object.
      get_hero().start_grabbing();
      get_lua_context().destructible_on_looked(*this);
    }

    return true;
  }

  return false;
}
Exemple #25
0
/**
 * \brief Notifies this detector that the player is interacting with it by
 * pressing the action command.
 *
 * This function is called when the player presses the action command
 * while the hero is facing this detector, and the action command effect lets
 * him do this.
 * The hero lifts the bomb if possible.
 */
void Bomb::notify_action_command_pressed() {

  KeysEffect::ActionKeyEffect effect = get_keys_effect().get_action_key_effect();

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

    get_hero().start_lifting(new CarriedItem(get_hero(), *this,
	"entities/bomb", "", 0, explosion_date));
    Sound::play("lift");
    remove_from_map();
  }
}
Exemple #26
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_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_THROW);
  get_sprites().set_animation_lifting();
  get_sprites().set_lifted_item(lifted_item);
  get_hero().set_facing_entity(nullptr);

  get_equipment().notify_ability_used(ABILITY_LIFT);
}
Exemple #27
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_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);

  Hero& hero = get_hero();
  if (stairs.is_inside_floor()) {
    if (way == Stairs::NORMAL_WAY) {
      // Towards an upper layer: change the layer now
      Layer layer = stairs.get_layer();
      Debug::check_assertion(layer != LAYER_HIGH, "Invalid stairs layer");
      get_entities().set_entity_layer(hero, Layer(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);
}
Exemple #28
0
/**
 * @brief This function is called when the player interacts with this chest.
 *
 * This function is called when the player presses the action key
 * when the hero is facing this detector, and the action icon lets him do this.
 * The hero opens the chest if possible.
 */
void Chest::action_key_pressed() {

  if (is_visible() && get_hero().is_free()) {

    if (!big_chest || get_equipment().has_ability("open_dungeon_big_locks")) {
      Sound::play("chest_open");
      set_open(true);
      treasure_date = System::now() + 300;

      get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);
      get_hero().start_freezed();
    }
    else {
      Sound::play("wrong");
      get_dialog_box().start_dialog("_big_key_required");
    }
  }
}
Exemple #29
0
/**
 * \brief Notifies this state that the action command was just pressed.
 */
void Hero::FreeState::notify_action_command_pressed() {

  if (get_keys_effect().is_action_key_acting_on_facing_entity()) {

    // action on the facing entity
    hero.get_facing_entity()->notify_action_command_pressed();
  }
  else if (hero.is_facing_point_on_obstacle()) {

    // grab an obstacle
    hero.set_state(new GrabbingState(hero));
  }
  else if (get_equipment().has_ability("run")) {

    // run
    hero.start_running();
  }
}
Exemple #30
0
/**
 * @brief Starts this state.
 * @param previous_state the previous state
 */
void Hero::StairsState::start(State* previous_state) {

  State::start(previous_state);

  // movement
  int speed = stairs.is_inside_floor() ? 40 : 24;
  std::string path = stairs.get_path(way);
  PathMovement* movement = new PathMovement(path, speed, false, true, false);

  // sprites and sound
  HeroSprites& sprites = get_sprites();
  if (carried_item == NULL) {
    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_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE);

  if (stairs.is_inside_floor()) {
    if (way == Stairs::NORMAL_WAY) {
      // low layer to intermediate layer: change the layer now
      get_entities().set_entity_layer(hero, LAYER_INTERMEDIATE);
    }
  }
  else {
    sprites.set_clipping_rectangle(stairs.get_clipping_rectangle(way));
    if (way == Stairs::REVERSE_WAY) {
      Rectangle 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.get_x(), hero.get_y() - dxy.get_y() + fix_y);
    }
  }
  hero.set_movement(movement);
}