@Override
  protected void writeImpl(AionConnection con) {
    writeD(effector.getObjectId());
    writeC(targetType);
    switch (targetType) {
      case 0:
      case 3:
      case 4:
        writeD(target.getObjectId());
        break;
      case 1:
        writeF(skill.getX());
        writeF(skill.getY());
        writeF(skill.getZ());
        break;
      case 2:
        writeF(skill.getX());
        writeF(skill.getY());
        writeF(skill.getZ());
        writeF(0); // unk1
        writeF(0); // unk2
        writeF(0); // unk3
        writeF(0); // unk4
        writeF(0); // unk5
        writeF(0); // unk6
        writeF(0); // unk7
        writeF(0); // unk8
        break;
    }
    writeH(skill.getSkillTemplate().getSkillId());
    writeC(skill.getSkillTemplate().getLvl());
    writeD(cooldown);
    writeH(hitTime);
    writeC(0); // unk

    /**
     * 0 : chain skill (counter too) 16 : no damage to all target like dodge, resist or effect size
     * is 0 32 : regular
     */
    if (effects.isEmpty()) writeH(16);
    else if (chainSuccess) writeH(32);
    else writeH(0);

    // Get dash status
    writeC(this.dashStatus);
    switch (this.dashStatus) {
      case 1:
      case 2:
      case 3:
      case 4:
      case 6:
        writeC(skill.getH());
        writeF(skill.getX());
        writeF(skill.getY());
        writeF(skill.getZ());
        break;
      default:
        break;
    }

    writeH(effects.size());
    for (Effect effect : effects) {
      Creature effected = effect.getEffected();

      if (effected != null) {
        writeD(effected.getObjectId());
        writeC(effect.getEffectResult().getId()); // 0 - NORMAL, 1 - ABSORBED, 2 - CONFLICT
        writeC(
            (int)
                (100f
                    * effected.getLifeStats().getCurrentHp()
                    / target.getLifeStats().getMaxHp())); // target %hp
      } else { // point point skills
        writeD(0);
        writeC(0);
        writeC(0);
      }

      writeC(
          (int)
              (100f
                  * effector.getLifeStats().getCurrentHp()
                  / effector.getLifeStats().getMaxHp())); // attacker %hp

      /**
       * Spell Status 1 : stumble 2 : knockback 4 : open aerial 8 : close aerial 16 : spin 32 :
       * block 64 : parry 128 :dodge 256 : resist
       */
      writeC(this.spellStatus);
      writeC(effect.getSkillMoveType().getId());
      writeH(0);
      writeC(effect.getCarvedSignet()); // current carve signet count

      switch (this.spellStatus) {
        case 1:
        case 2:
        case 4:
        case 8:
          writeF(effect.getTargetX());
          writeF(effect.getTargetY());
          writeF(effect.getTargetZ());
          break;
        case 16:
          writeC(effect.getEffector().getHeading());
          break;
        default:
          switch (effect.getSkillMoveType()) {
            case PULL:
            case KNOCKBACK:
              writeF(effect.getTargetX());
              writeF(effect.getTargetY());
              writeF(effect.getTargetZ());
            default:
              break;
          }
          break;
      }

      writeC(1); // loops size - always 1?
      // TODO for(lop size)
      {
        writeC(effect.isMphealInstant() ? 1 : 0);
        if (effect.isDelayedDamage()) writeD(0);
        else writeD(effect.getReserved1()); // TODO value from specific effect using loop
        writeC(effect.getAttackStatus().getId());

        // setting counter skill from packet to have the best synchronization of time with client
        if (effect.getEffected() instanceof Player) {
          if (effect.getAttackStatus().isCounterSkill())
            ((Player) effect.getEffected()).setLastCounterSkill(effect.getAttackStatus());
        }

        writeC(effect.getShieldDefense());

        /**
         * shield Type: 1: reflector 2: normal shield 8: protect effect (ex. skillId: 417 Bodyguard)
         * TODO find out 4
         */
        switch (effect.getShieldDefense()) {
          case 0:
          case 2:
            break;
          case 8:
          case 10:
            writeD(effect.getProtectorId()); // protectorId
            writeD(effect.getProtectedDamage()); // protected damage
            writeD(effect.getProtectedSkillId()); // skillId
            break;
          case 16:
            writeD(0);
            writeD(0);
            writeD(0);
            writeD(0);
            writeD(0);
            writeD(effect.getMpShield());
            writeD(effect.getReflectedSkillId());
            break;
          default:
            writeD(effect.getProtectorId()); // protectorId
            writeD(effect.getProtectedDamage()); // protected damage
            writeD(effect.getProtectedSkillId()); // skillId
            writeD(effect.getReflectedDamage()); // reflect damage
            writeD(effect.getReflectedSkillId()); // skill id
            writeD(0);
            writeD(0);
            break;
        }
      }
    }
  }