/** @param npcAI */
  protected static void skillAction(NpcAI2 npcAI) {
    Creature target = (Creature) npcAI.getOwner().getTarget();
    if (npcAI.getOwner().getObjectTemplate().getAttackRange() == 0) {
      if (npcAI.getOwner().getTarget() != null
          && !MathUtil.isInRange(
              npcAI.getOwner(), npcAI.getOwner().getTarget(), npcAI.getOwner().getAggroRange())) {
        npcAI.onGeneralEvent(AIEventType.TARGET_TOOFAR);
        npcAI.getOwner().getController().abortCast();
        return;
      }
    }
    if (target != null && !target.getLifeStats().isAlreadyDead()) {
      final int skillId = npcAI.getSkillId();
      final int skillLevel = npcAI.getSkillLevel();

      SkillTemplate template = DataManager.SKILL_DATA.getSkillTemplate(skillId);
      int duration = template.getDuration();
      if (npcAI.isLogging()) {
        AI2Logger.info(
            npcAI, "Using skill " + skillId + " level: " + skillLevel + " duration: " + duration);
      }
      switch (template.getSubType()) {
        case BUFF:
          switch (template.getProperties().getFirstTarget()) {
            case ME:
              if (npcAI.getOwner().getEffectController().isAbnormalPresentBySkillId(skillId)) {
                afterUseSkill(npcAI);
                return;
              }
              break;
            default:
              if (target.getEffectController().isAbnormalPresentBySkillId(skillId)) {
                afterUseSkill(npcAI);
                return;
              }
          }
          break;
      }
      boolean success = npcAI.getOwner().getController().useSkill(skillId, skillLevel);
      if (!success) {
        afterUseSkill(npcAI);
      }
    } else {
      npcAI.setSubStateIfNot(AISubState.NONE);
      npcAI.onGeneralEvent(AIEventType.TARGET_GIVEUP);
    }
  }
 /**
  * @param npcAI
  * @param delay
  */
 public static void performAttack(NpcAI2 npcAI, int delay) {
   if (npcAI.getOwner().getObjectTemplate().getAttackRange() == 0) {
     if (npcAI.getOwner().getTarget() != null
         && !MathUtil.isInRange(
             npcAI.getOwner(), npcAI.getOwner().getTarget(), npcAI.getOwner().getAggroRange())) {
       npcAI.onGeneralEvent(AIEventType.TARGET_TOOFAR);
       npcAI.getOwner().getController().abortCast();
       return;
     }
   }
   if (npcAI.setSubStateIfNot(AISubState.CAST)) {
     if (delay > 0) {
       ThreadPoolManager.getInstance()
           .schedule(
               new SkillAction(npcAI),
               delay + DataManager.SKILL_DATA.getSkillTemplate(npcAI.getSkillId()).getDuration());
     } else {
       skillAction(npcAI);
     }
   }
 }