/** * @brief Creates a new destructible item with the specified subtype. * @param name Unique name identifying the entity on the map or an empty string. * @param layer layer of the destructible item to create on the map * @param x x coordinate of the destructible item to create * @param y y coordinate of the destructible item to create * @param subtype subtype of destructible item to create * @param treasure the pickable item that appears when the destructible * item is lifted or cut */ Destructible::Destructible(const std::string& name, Layer layer, int x, int y, Subtype subtype, const Treasure &treasure): Detector(COLLISION_NONE, name, layer, x, y, 16, 16), subtype(subtype), treasure(treasure), is_being_cut(false), regeneration_date(0), is_regenerating(false), destruction_callback_ref(LUA_REFNIL) { set_origin(8, 13); create_sprite(get_animation_set_id()); // set the collision mode if (features[subtype].can_be_lifted) { add_collision_mode(COLLISION_FACING_POINT); } if (features[subtype].can_be_cut || features[subtype].can_explode) { add_collision_mode(COLLISION_SPRITE); } if (has_special_ground()) { // display a special ground under the hero add_collision_mode(COLLISION_CUSTOM); } }
/** * \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); } } } }
/** * \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; }
/** * \brief Sets the current direction of the sprite's animation and restarts the animation. * * If the specified direction is the current direction, nothing is done. * * \param current_direction the current direction */ void Sprite::set_current_direction(int current_direction) { if (current_direction != this->current_direction) { Debug::check_assertion(current_direction >= 0 && current_direction < get_nb_directions(), StringConcat() << "Invalid direction " << current_direction << " for sprite '" << get_animation_set_id() << "' in animation '" << current_animation_name << "'"); this->current_direction = current_direction; set_current_frame(0, false); if (lua_context != NULL) { lua_context->sprite_on_direction_changed(*this, current_animation_name, current_direction); lua_context->sprite_on_frame_changed(*this, current_animation_name, 0); } } }