/** * \brief Notifies this enemy that it should restart his movement. * * This function is called when the enemy needs to restart its movement * because something happened (for example the enemy has just been created, * or it was just hurt). * By default, the "walking" animation is set on the enemy's sprites. */ void Enemy::restart() { if (is_immobilized()) { stop_immobilized(); } set_animation("walking"); get_lua_context().enemy_on_restarted(*this); }
/** * \brief Makes the enemy receive an attack. * * He might resist to the attack or get hurt. * * \param attack type of attack * \param source the entity attacking the enemy (often the hero) * \param this_sprite the sprite of this enemy that received the attack, or NULL * if the attack comes from a non pixel-precise collision test */ void Enemy::try_hurt(EnemyAttack attack, MapEntity& source, Sprite* this_sprite) { EnemyReaction::Reaction reaction = get_attack_consequence(attack, this_sprite); if (invulnerable || reaction.type == EnemyReaction::IGNORED) { // ignore the attack return; } invulnerable = true; vulnerable_again_date = System::now() + 500; switch (reaction.type) { case EnemyReaction::PROTECTED: // attack failure sound Sound::play("sword_tapping"); break; case EnemyReaction::IMMOBILIZED: // get immobilized hurt(source); immobilize(); notify_hurt(source, attack, 0); break; case EnemyReaction::CUSTOM: // custom attack (defined in the script) if (is_in_normal_state()) { custom_attack(attack, this_sprite); } else { // no attack was made: notify the source correctly reaction.type = EnemyReaction::IGNORED; invulnerable = false; } break; case EnemyReaction::HURT: if (is_immobilized() && get_sprite().get_current_animation() == "shaking") { stop_immobilized(); } // compute the number of health points lost by the enemy if (attack == ATTACK_SWORD) { // for a sword attack, the damage depends on the sword and the variant of sword attack used int damage_multiplicator = ((Hero&) source).get_sword_damage_factor(); reaction.life_lost *= damage_multiplicator; } else if (attack == ATTACK_THROWN_ITEM) { reaction.life_lost *= ((CarriedItem&) source).get_damage_on_enemies(); } life -= reaction.life_lost; hurt(source); notify_hurt(source, attack, reaction.life_lost); break; case EnemyReaction::IGNORED: case EnemyReaction::REACTION_NUMBER: Debug::die(StringConcat() << "Invalid enemy reaction" << reaction.type); break; } // notify the source source.notify_attacked_enemy(attack, *this, reaction, get_life() <= 0); }
/** * \brief Makes the enemy receive an attack. * * He might resist to the attack or get hurt. * * \param attack type of attack * \param source the entity attacking the enemy (often the hero) * \param this_sprite the sprite of this enemy that received the attack, or NULL * if the attack comes from a non pixel-precise collision test */ void Enemy::try_hurt(EnemyAttack attack, MapEntity& source, Sprite* this_sprite) { EnemyReaction::Reaction reaction = get_attack_consequence(attack, this_sprite); if (invulnerable || reaction.type == EnemyReaction::IGNORED) { // ignore the attack return; } invulnerable = true; vulnerable_again_date = System::now() + 500; switch (reaction.type) { case EnemyReaction::PROTECTED: // attack failure sound Sound::play("sword_tapping"); break; case EnemyReaction::IMMOBILIZED: // get immobilized being_hurt = true; hurt(source, this_sprite); immobilize(); break; case EnemyReaction::CUSTOM: // custom attack (defined in the script) if (is_in_normal_state()) { custom_attack(attack, this_sprite); } else { // no attack was made: notify the source correctly reaction.type = EnemyReaction::IGNORED; invulnerable = false; } break; case EnemyReaction::HURT: if (is_immobilized() && get_sprite().get_current_animation() == "shaking") { stop_immobilized(); } // Compute the number of health points lost by the enemy. being_hurt = true; if (attack == ATTACK_SWORD) { Hero& hero = static_cast<Hero&>(source); // Sword attacks only use pixel-precise collisions. Debug::check_assertion(this_sprite != NULL, "Missing enemy sprite for sword attack" ); // For a sword attack, the damage may be something customized. bool customized = get_lua_context().enemy_on_hurt_by_sword( *this, hero, *this_sprite); if (customized) { reaction.life_lost = 0; // Already done by the script. } else { // If this is not customized, the default it to multiply the reaction // by a factor that depends on the sword. reaction.life_lost *= hero.get_sword_damage_factor(); } } else if (attack == ATTACK_THROWN_ITEM) { reaction.life_lost *= static_cast<CarriedItem&>(source).get_damage_on_enemies(); } life -= reaction.life_lost; hurt(source, this_sprite); notify_hurt(source, attack); break; case EnemyReaction::IGNORED: case EnemyReaction::REACTION_NUMBER: { std::ostringstream oss; oss << "Invalid enemy reaction: " << reaction.type; Debug::die(oss.str()); break; } } // notify the source source.notify_attacked_enemy( attack, *this, this_sprite, reaction, get_life() <= 0 ); }