Example #1
0
/**
 * @brief Makes the door immediately open or closed.
 * @param door_open true to make it opened, false to make it closed.
 */
void Door::set_open(bool door_open) {

  state = door_open ? OPEN : CLOSED;

  if (door_open) {
    set_collision_modes(COLLISION_NONE); // to avoid being the hero's facing entity
  }
  else {
    get_sprite().set_current_animation("closed");
    set_collision_modes(COLLISION_FACING_POINT | COLLISION_SPRITE);

    // ensure that we are not closing the door on the hero
    if (is_on_map() && overlaps(get_hero())) {
      get_hero().avoid_collision(*this, (get_direction() + 2) % 4);
    }
  }

  if (is_on_map()) {
    update_dynamic_tiles();

    if (is_saved()) {
      get_savegame().set_boolean(savegame_variable, door_open);
    }

    if (door_open) {
      get_lua_context().door_on_opened(*this);
    }
    else {
      get_lua_context().door_on_closed(*this);
    }
  }
}
Example #2
0
/**
 * \brief Constructor.
 * \param name Name of the teletransporter.
 * \param layer Layer of the teletransporter.
 * \param xy Coordinates where to create the entity.
 * \param size Size of the teletransporter's rectangle.
 * \param sprite_name Sprite animation set id to use, or an empty string.
 * \param sound_id Sound to play when using the teletransporter,
 * or an empty string.
 * \param transition_style Style of transition between the two maps.
 * \param destination_map_id Id of the destination map.
 * \param destination_name Location on the destination map,
 * or "_same" to keep the hero's coordinates,
 * or "_side" to place the hero on the appropriate side of the map.
 * An empty string means the default destination entity of the map.
 */
Teletransporter::Teletransporter(
    const std::string& name,
    int layer,
    const Point& xy,
    const Size& size,
    const std::string& sprite_name,
    const std::string& sound_id,
    Transition::Style transition_style,
    const std::string& destination_map_id,
    const std::string& destination_name):

  Entity(name, 0, layer, xy, size),
  sound_id(sound_id),
  transition_style(transition_style),
  destination_map_id(destination_map_id),
  destination_name(destination_name),
  destination_side(-1),
  transition_direction(0),
  transporting_hero(false) {

  set_collision_modes(CollisionMode::COLLISION_CUSTOM);

  if (!sprite_name.empty()) {
    create_sprite(sprite_name);
  }
}
Example #3
0
/**
 * \brief Creates a block.
 * \param name name identifying this block
 * \param layer layer of the entity to create
 * \param xy Coordinate of the entity to create.
 * \param direction the only direction where the block can be moved
 * or -1 to allow it to be pushed in any direction
 * \param sprite_name animation set id of the sprite for this block
 * \param can_be_pushed true to allow the hero to push this block
 * \param can_be_pulled true to allow the hero to pull this block
 * \param maximum_moves indicates how many times the block can
 * be moved (0: none, 1: once, 2: infinite)
 */
Block::Block(
    const std::string& name,
    int layer,
    const Point& xy,
    int direction,
    const std::string& sprite_name,
    bool can_be_pushed,
    bool can_be_pulled,
    int maximum_moves
):
  Entity(name, direction, layer, xy, Size(16, 16)),
  maximum_moves(maximum_moves),
  sound_played(false),
  when_can_move(System::now()),
  last_position(xy),
  initial_position(xy),
  initial_maximum_moves(maximum_moves),
  can_be_pushed(can_be_pushed),
  can_be_pulled(can_be_pulled) {

  Debug::check_assertion(maximum_moves >= 0 && maximum_moves <= 2,
      "maximum_moves must be between 0 and 2");

  set_collision_modes(CollisionMode::COLLISION_FACING);
  set_origin(8, 13);
  set_direction(direction);
  const SpritePtr& sprite = create_sprite(sprite_name);
  set_drawn_in_y_order(sprite->get_size().height > 16);
}
Example #4
0
/**
 * \brief Constructor.
 *
 * Creates a bomb.
 *
 * \param name Name identifying the entity on the map or an empty string.
 * \param layer layer of the entity to create
 * \param xy Coordinates of the entity to create.
 */
Bomb::Bomb(const std::string& name, int layer, const Point& xy):
  Entity(name, 0, layer, xy, Size(16, 16)),
  explosion_date(System::now() + 6000) {

  set_collision_modes(CollisionMode::COLLISION_FACING);
  const SpritePtr& sprite = create_sprite("entities/bomb");
  sprite->enable_pixel_collisions();
  set_size(16, 16);
  set_origin(8, 13);
  set_drawn_in_y_order(true);
}
Example #5
0
/**
 * \brief Kills the enemy.
 *
 * This function is called when the enemy has no more health points.
 */
void Enemy::kill() {

  // if the enemy is immobilized, give some money
  if (rank == RANK_NORMAL && is_immobilized() && !treasure.is_saved()) {
    // TODO choose random money (can we do this from scripts?)
  }

  // stop any movement and disable attacks
  set_collision_modes(COLLISION_NONE);
  clear_movement();
  invulnerable = true;
  can_attack = false;
  can_attack_again_date = 0;
  dying_animation_started = true;

  if (hurt_style == HURT_BOSS) {
    // A boss: create some explosions.
    exploding = true;
    nb_explosions = 0;
    next_explosion_date = System::now() + 2000;
  }
  else {
    // Replace the enemy sprites.
    clear_sprites();
    switch (get_ground_below()) {

      case GROUND_HOLE:
        // TODO animation of falling into a hole.
        Sound::play("jump");
        break;

      case GROUND_DEEP_WATER:
        // TODO water animation.
        Sound::play("splash");
        break;

      case GROUND_LAVA:
        // TODO lava animation.
        Sound::play("splash");
        break;

      default:
        create_sprite("enemies/enemy_killed");
        Sound::play("enemy_killed");
        break;
    }
  }

  // save the enemy state if required
  if (is_saved()) {
    get_savegame().set_boolean(savegame_variable, true);
  }
}
Example #6
0
/**
 * \brief Sets the appropriate collisions modes.
 *
 * This depends on whether the object is an obstacle, can be cut
 * or can explode.
 */
void Destructible::update_collision_modes() {

  // Reset previous collision modes.
  set_collision_modes(0);

  // Sets the new ones.
  if (get_modified_ground() == Ground::WALL) {
    // The object is an obstacle.
    // Set the facing collision mode to allow the hero to look at it.
    add_collision_mode(COLLISION_FACING);
  }

  if (get_can_be_cut()
      || get_can_explode()) {
    add_collision_mode(COLLISION_SPRITE);
  }
}
Example #7
0
/**
 * \brief Creates an NPC.
 * \param game the game
 * \param name name identifying this NPC
 * \param layer layer of the entity to create
 * \param xy Coordinates of the entity to create.
 * \param subtype the subtype of interaction
 * \param sprite_name sprite animation set of the entity, or an empty string to create no sprite
 * \param direction for a generalized NPC: direction for which the interactions are allowed
 * (0 to 4, or -1 for any direction), for a usual NPC: initial direction of the NPC's sprite
 * \param behavior_string indicates what happens when the hero interacts with this NPC:
 * "dialog#XXX" to start the dialog XXX, "map" to call the map script
 * (with an event_hero_interaction() call) or "item#XXX" to call the script
 * of item XXX  (with an event_hero_interaction() call)
 */
Npc::Npc(
    Game& /* game */,
    const std::string& name,
    int layer,
    const Point& xy,
    Subtype subtype,
    const std::string& sprite_name,
    int direction,
    const std::string& behavior_string
):
  Entity(name, 0, layer, xy, Size(0, 0)),
  subtype(subtype),
  behavior(BEHAVIOR_MAP_SCRIPT),
  traversable(false),
  dialog_to_show(""),
  item_name("") {

  set_collision_modes(CollisionMode::COLLISION_FACING | CollisionMode::COLLISION_OVERLAPPING);
  initialize_sprite(sprite_name, direction);
  set_size(16, 16);
  set_origin(8, 13);
  set_direction(direction);

  // Usual NPCs are displayed like the hero whereas generalized NPCs are
  // not necessarily people.
  set_drawn_in_y_order(subtype == USUAL_NPC);

  // behavior
  if (behavior_string == "map") {
    behavior = BEHAVIOR_MAP_SCRIPT;
  }
  else if (behavior_string.substr(0, 5) == "item#") {
    behavior = BEHAVIOR_ITEM_SCRIPT;
    item_name = behavior_string.substr(5);
  }
  else if (behavior_string.substr(0, 7) == "dialog#") {
    behavior = BEHAVIOR_DIALOG;
    dialog_to_show = behavior_string.substr(7);
  }
  else {
    Debug::die(std::string("Invalid behavior string for NPC '") + name
        + "': '" + behavior_string + "'");
  }
}
Example #8
0
/**
 * \brief Creates a new crystal block.
 * \param game The current game.
 * \param name Name identifying the entity on the map or an empty string.
 * \param layer Layer of the entity to create on the map.
 * \param xy Coordinates of the entity to create.
 * \param size Size of the block (the pattern can be repeated).
 * \param subtype subtype of raised block
 */
CrystalBlock::CrystalBlock(Game& game, const std::string& name,
    int layer, const Point& xy, const Size& size, Subtype subtype):
  Entity(name, 0, layer, xy, size),
  subtype(subtype) {

  set_collision_modes(CollisionMode::COLLISION_OVERLAPPING);
  Sprite& sprite = *create_sprite("entities/crystal_block");

  // Don't pause the sprite animation when the crystal block is far from the
  // camera. Otherwise it looks weird if the players comes back using a
  // teletransporter.
  sprite.set_ignore_suspend(true);

  this->orange_raised = game.get_crystal_state();

  if (subtype == ORANGE) {
    sprite.set_current_animation(orange_raised ? "orange_raised" : "orange_lowered");
  }
  else {
    sprite.set_current_animation(orange_raised ? "blue_lowered" : "blue_raised");
  }
  sprite.set_current_frame(sprite.get_nb_frames() - 1); // to avoid the animations at the map beginning
}
Example #9
0
/**
 * \brief Adds a collision mode to this detector.
 * \param collision_mode the collision mode to add
 */
void Detector::add_collision_mode(CollisionMode collision_mode) {

  set_collision_modes(this->collision_modes | collision_mode);
}
Example #10
0
/**
 * \brief Unregisters all collision test functions.
 */
void CustomEntity::clear_collision_tests() {

    // Disable all collisions checks.
    collision_tests.clear();
    set_collision_modes(COLLISION_FACING);
}