/** * \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(); } }
/** * \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()) { Hero& hero = get_hero(); 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 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) { 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); } } }