/** * \brief Starts this state. * \param previous_state the previous state */ void Hero::HurtState::start(const State* previous_state) { State::start(previous_state); Equipment& equipment = get_equipment(); Sound::play("hero_hurt"); if (life_points != 0) { // the level of the tunic reduces the damage, but we remove at least 1 life point life_points = std::max(1, life_points / (equipment.get_ability("tunic"))); equipment.remove_life(life_points); if (equipment.has_ability("tunic")) { equipment.notify_ability_used("tunic"); } } if (magic_points > 0 && equipment.get_magic() > 0) { equipment.remove_magic(magic_points); Sound::play("magic_bar"); } get_sprites().set_animation_hurt(); get_sprites().blink(); Hero& hero = get_hero(); double angle = Geometry::get_angle(source_xy.get_x(), source_xy.get_y(), hero.get_x(), hero.get_y()); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(24); movement->set_speed(120); movement->set_angle(angle); hero.set_movement(movement); end_hurt_date = System::now() + 200; }
/** * \brief Notifies this state that the hero has just attacked an enemy. * \param attack the attack * \param victim the enemy just hurt * \param result indicates how the enemy has reacted to the attack (see Enemy.h) * \param killed indicates that the attack has just killed the enemy */ void Hero::SpinAttackState::notify_attacked_enemy( EnemyAttack attack, Enemy& victim, EnemyReaction::Reaction& result, bool killed) { Hero& hero = get_hero(); if (result.type != EnemyReaction::IGNORED && attack == ATTACK_SWORD) { if (victim.get_push_hero_on_sword()) { if (hero.get_movement() != NULL) { // interrupting a super spin attack: finish with a normal one hero.clear_movement(); get_sprites().set_animation_spin_attack(); } being_pushed = true; double angle = Geometry::get_angle(victim.get_x(), victim.get_y(), hero.get_x(), hero.get_y()); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(24); movement->set_speed(120); movement->set_angle(angle); hero.set_movement(movement); } } }
/** * \brief Hurts the enemy. * * Updates its state, its sprite and plays the sound. * * \param source the entity attacking the enemy (often the hero) */ void Enemy::hurt(MapEntity& source) { uint32_t now = System::now(); // update the enemy state being_hurt = true; set_movement_events_enabled(false); can_attack = false; can_attack_again_date = now + 300; // graphics and sounds set_animation("hurt"); play_hurt_sound(); // stop any movement clear_movement(); // push the enemy back if (pushed_back_when_hurt) { double angle = source.get_angle(*this); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(24); movement->set_speed(120); movement->set_angle(angle); set_movement(movement); } stop_hurt_date = now + 300; }
/** * \brief Creates a boomerang. * \param hero the hero * \param max_distance maximum distance of the movement in pixels * \param speed speed of the movement in pixels per second * \param angle the angle of the boomerang trajectory in radians * \param sprite_name animation set id representing the boomerang */ Boomerang::Boomerang( Hero& hero, int max_distance, int speed, double angle, const std::string& sprite_name): MapEntity("", 0, hero.get_layer(), 0, 0, 0, 0), hero(hero), has_to_go_back(false), going_back(false), speed(speed) { // initialize the entity create_sprite(sprite_name); set_size(16, 16); set_origin(8, 8); int hero_x = hero.get_top_left_x(); int hero_y = hero.get_top_left_y(); switch (hero.get_animation_direction()) { case 0: set_xy(hero_x + 24, hero_y + 8); break; case 1: set_xy(hero_x + 8, hero_y - 8); break; case 2: set_xy(hero_x - 8, hero_y + 8); break; case 3: set_xy(hero_x + 8, hero_y + 24); break; } initial_coords.set_xy(get_xy()); StraightMovement* movement = new StraightMovement(false, false); movement->set_speed(speed); movement->set_angle(angle); movement->set_max_distance(max_distance); set_movement(movement); next_sound_date = System::now(); }
/** * @brief Notifies this state that the hero has just attacked an enemy. * @param attack the attack * @param victim the enemy just hurt * @param result indicates how the enemy has reacted to the attack (see Enemy.h) * @param killed indicates that the attack has just killed the enemy */ void Hero::SwordSwingingState::notify_attacked_enemy(EnemyAttack attack, Enemy& victim, EnemyReaction::Reaction& result, bool killed) { if (result.type != EnemyReaction::IGNORED && attack == ATTACK_SWORD) { attacked = true; if (victim.get_push_hero_on_sword()) { double angle = Geometry::get_angle(victim.get_x(), victim.get_y(), hero.get_x(), hero.get_y()); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(24); movement->set_speed(120); movement->set_angle(angle); hero.set_movement(movement); } } }
/** * \brief Starts this state. * \param previous_state The previous state. */ void Hero::HurtState::start(const State* previous_state) { State::start(previous_state); Equipment& equipment = get_equipment(); Sound::play("hero_hurt"); Hero& hero = get_hero(); const uint32_t invincibility_duration = 2000; hero.set_invincible(true, invincibility_duration); get_sprites().set_animation_hurt(); get_sprites().blink(invincibility_duration); if (has_source) { double angle = Geometry::get_angle(source_xy.get_x(), source_xy.get_y(), hero.get_x(), hero.get_y()); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(24); movement->set_speed(120); movement->set_angle(angle); hero.set_movement(movement); } end_hurt_date = System::now() + 200; // See if the script customizes how the hero takes damages. bool handled = get_lua_context().hero_on_taking_damage(get_hero(), damage); if (!handled && damage != 0) { // No customized damage: perform the default calculation. // The level of the tunic reduces the damage, // but we remove at least 1 life point. int life_points = std::max(1, damage / (equipment.get_ability(ABILITY_TUNIC))); equipment.remove_life(life_points); if (equipment.has_ability(ABILITY_TUNIC)) { equipment.notify_ability_used(ABILITY_TUNIC); } } }
/** * \brief Updates this state. */ void Hero::RunningState::update() { State::update(); if (is_suspended()) { return; } uint32_t now = System::now(); if (!is_bouncing() && now >= next_sound_date) { Sound::play("running"); next_sound_date = now + 170; } Hero& hero = get_hero(); if (phase == 0) { if (now >= next_phase_date) { double angle = Geometry::degrees_to_radians(get_sprites().get_animation_direction() * 90); StraightMovement* movement = new StraightMovement(false, true); movement->set_max_distance(3000); movement->set_speed(300); movement->set_angle(angle); hero.clear_movement(); hero.set_movement(movement); get_sprites().set_animation_running(); phase++; } else if (!is_pressing_running_key()) { hero.set_state(new FreeState(hero)); } } else if (hero.get_movement()->is_finished()) { hero.start_state_from_ground(); } }