예제 #1
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
      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);
}
예제 #2
0
파일: Enemy.cpp 프로젝트: j4b0l/solarus
/**
 * \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
  );
}