/** * @brief Creates a door. * @param game The game. * @param name Name identifying this entity. * @param layer Layer of the entity to create. * @param x X coordinate of the entity to create. * @param y Y coordinate of the entity to create. * @param direction Direction of the door. * @param sprite_name Name of the animation set of the * sprite to create for the door. * The sprite must have an animation \c "closed", that will be shown while * the door is closed. Optionally, they sprite can also have animations * \c "opening" and \c "closing", that will be shown (if they exist) * while the door is being opened or closed, respectively. * If they don't exist, the door will get opened or closed instantly. * @param savegame_variable Boolean variable where the door's state is saved * (an empty string lets the door unsaved). */ Door::Door(Game& game, const std::string& name, Layer layer, int x, int y, int direction, const std::string& sprite_name, const std::string& savegame_variable): Detector(COLLISION_FACING_POINT | COLLISION_SPRITE, name, layer, x, y, 16, 16), savegame_variable(savegame_variable), opening_method(OPENING_NONE), opening_condition(), opening_condition_consumed(false), cannot_open_dialog_id(), state(OPEN), initialized(false), next_hint_sound_date(0) { Sprite& sprite = create_sprite(sprite_name, true); sprite.set_ignore_suspend(true); // Continue the animation while the camera is moving. set_direction(direction); if (is_saved()) { set_open(game.get_savegame().get_boolean(savegame_variable)); } else { set_open(false); } sprite.set_current_direction(direction); }
/** * @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 opens the door if possible, otherwise a message is shown. */ void Door::notify_action_command_pressed() { if (get_hero().is_free() && is_closed()) { if (can_open()) { Sound::play("door_unlocked"); Sound::play("door_open"); if (is_saved()) { get_savegame().set_boolean(savegame_variable, true); } if (is_opening_condition_consumed()) { consume_opening_condition(); } set_opening(); get_hero().check_position(); } else if (!cannot_open_dialog_id.empty()) { Sound::play("wrong"); get_dialog_box().start_dialog(cannot_open_dialog_id); } } }
/** * @brief Updates the entity. */ void Door::update() { Detector::update(); if (!initialized) { update_dynamic_tiles(); initialized = true; } if (is_closed() && get_opening_method() == OPENING_BY_EXPLOSION && get_equipment().has_ability("detect_weak_walls") && Geometry::get_distance(get_center_point(), get_hero().get_center_point()) < 40 && !is_suspended() && System::now() >= next_hint_sound_date) { Sound::play("cane"); next_hint_sound_date = System::now() + 500; } if (is_changing() && get_sprite().is_animation_finished()) { // Toggle door_open when the changing animation finishes. set_open(is_opening()); } if (is_saved() && !is_changing()) { bool open_in_savegame = get_savegame().get_boolean(savegame_variable); if (open_in_savegame && is_closed()) { set_opening(); } else if (!open_in_savegame && is_open()) { set_closing(); } } }
/** * @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); } } }
// проверяет, все ли документы сохранены bool CController::is_saved() { for (int type = ORDER; type < QUANTITY_TYPES; type++) { if (!is_saved((DocumentType)type)) { return false; } } return true; }
/** * \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); } }
/** * @brief Starts closing the door and plays the corresponding animations. * * Nothing is done if the door is already in the process of being closed. */ void Door::close() { if (is_closed() || is_closing()) { // The door is already closed or being closed: nothing to do. return; } set_closing(); if (is_saved()) { get_savegame().set_boolean(savegame_variable, false); } }
/** * @brief Starts opening the door and plays the corresponding animations. * * Nothing is done if the door is already in the process of being open. */ void Door::open() { if (is_open() || is_opening()) { // The door is already open or being open: nothing to do. return; } set_opening(); if (is_saved()) { get_savegame().set_boolean(savegame_variable, true); } }
/** * \brief Gives the treasure to the player. * * Adds the item to the hero's equipment. * The item should not be empty. */ void Treasure::give_to_player() const { Debug::check_assertion(!is_found(), "This treasure was already found"); // Mark the treasure as found in the savegame. if (is_saved()) { game->get_savegame().set_boolean(savegame_variable, true); } // Give the item to the player. EquipmentItem& item = get_item(); if (item.is_saved()) { item.set_variant(get_variant()); } // Notify the Lua item and the Lua map. LuaContext& lua_context = game->get_lua_context(); lua_context.item_on_obtaining(item, *this); lua_context.map_on_obtaining_treasure(game->get_current_map(), *this); }
/** * \brief Returns whether the player has got this treasure according to th * savegame. * * Returns false if the treasure is not saved. * * \return true if the player has found this treasure. */ bool Treasure::is_found() const { return is_saved() && game->get_savegame().get_boolean(savegame_variable); }