public static final int[] getEnchantCatalystId(ItemInstance item) {
   if (item.getTemplate().isWeapon())
     switch (item.getGrade().getCrystalId()) {
       case ItemTemplate.CRYSTAL_A:
         return catalyst[3];
       case ItemTemplate.CRYSTAL_B:
         return catalyst[2];
       case ItemTemplate.CRYSTAL_C:
         return catalyst[1];
       case ItemTemplate.CRYSTAL_D:
         return catalyst[0];
       case ItemTemplate.CRYSTAL_S:
         return catalyst[4];
       case ItemTemplate.CRYSTAL_R:
         return catalyst[5];
     }
   else if (item.getTemplate().isArmor() || item.getTemplate().isAccessory())
     switch (item.getGrade().getCrystalId()) {
       case ItemTemplate.CRYSTAL_A:
         return catalyst[9];
       case ItemTemplate.CRYSTAL_B:
         return catalyst[8];
       case ItemTemplate.CRYSTAL_C:
         return catalyst[7];
       case ItemTemplate.CRYSTAL_D:
         return catalyst[6];
       case ItemTemplate.CRYSTAL_S:
         return catalyst[10];
       case ItemTemplate.CRYSTAL_R:
         return catalyst[11];
     }
   return new int[] {0};
 }
  /**
   * Проверяет соответствие уровня заточки и вообще катализатор ли это или левый итем
   *
   * @param item
   * @param catalyst
   * @return true если катализатор соответствует
   */
  public static final boolean checkCatalyst(ItemInstance item, ItemInstance catalyst) {
    if (item == null || catalyst == null) return false;

    int current = item.getEnchantLevel();
    if (current < (item.getTemplate().getBodyPart() == ItemTemplate.SLOT_FULL_ARMOR ? 4 : 3)
        || current > 9) return false;

    for (int catalystRequired : getEnchantCatalystId(item))
      if (catalystRequired == catalyst.getItemId()) return true;

    return false;
  }
  @Override
  protected final void writeImpl() {
    writeC(0x9a);
    writeS(_name);
    writeD(_limit); // c4?
    writeH(1); // show window ??

    writeH(_size);
    for (ItemInstance temp : _items) {
      if (!temp.getTemplate().isQuest()) writeItemInfo(_player, temp);
    }
  }
  /**
   * Проверяет возможность передачи вещи
   *
   * @param player
   * @param item
   * @return
   */
  public static final boolean checkIfCanDiscard(Player player, ItemInstance item) {
    if (item.isHeroItem()) return false;

    if (player.getMountControlItemObjId() == item.getObjectId()) return false;

    if (player.getPetControlItem() == item) return false;

    if (player.getEnchantScroll() == item) return false;

    if (item.isCursed()) return false;

    if (item.getTemplate().isQuest()) return false;

    return true;
  }
  public static long removeItem(Playable playable, ItemInstance item, long count, boolean notify) {
    long removed = 0;
    if (playable == null || count < 1) return removed;

    Playable player = playable.getPlayer();
    if (item.getTemplate().isStackable()) {
      if (player.getInventory().destroyItem(item, count)) removed = count;
    } else
      for (long i = 0; i < count; i++) if (player.getInventory().destroyItem(item, 1)) removed++;

    if (removed > 0 && notify)
      player.sendPacket(SystemMessage2.removeItems(item.getItemId(), removed));

    return removed;
  }
  public static final IStaticPacket checkIfCanEquip(PetInstance pet, ItemInstance item) {
    if (!item.isEquipable()) return SystemMsg.YOUR_PET_CANNOT_CARRY_THIS_ITEM;

    int petId = pet.getNpcId();

    if (item.getTemplate().isPendant() //
        || PetDataHolder.isWolf(petId) && item.getTemplate().isForWolf() //
        || PetDataHolder.isHatchling(petId) && item.getTemplate().isForHatchling() //
        || PetDataHolder.isStrider(petId) && item.getTemplate().isForStrider() //
        || PetDataHolder.isGreatWolf(petId) && item.getTemplate().isForGWolf() //
        || PetDataHolder.isBabyPet(petId) && item.getTemplate().isForPetBaby() //
        || PetDataHolder.isImprovedBabyPet(petId) && item.getTemplate().isForPetBaby() //
    ) return null;

    return SystemMsg.YOUR_PET_CANNOT_CARRY_THIS_ITEM;
  }
  public static boolean canAddItem(Player player, ItemInstance item) {
    if (!player.getInventory().validateWeight(item)) {
      player.sendPacket(SystemMsg.YOU_HAVE_EXCEEDED_THE_WEIGHT_LIMIT);
      return false;
    }

    if (!player.getInventory().validateCapacity(item)) {
      player.sendPacket(SystemMsg.YOUR_INVENTORY_IS_FULL);
      return false;
    }

    if (!item.getTemplate().getHandler().pickupItem(player, item)) return false;

    PickableAttachment attachment =
        item.getAttachment() instanceof PickableAttachment
            ? (PickableAttachment) item.getAttachment()
            : null;
    if (attachment != null && !attachment.canPickUp(player)) return false;

    return true;
  }
  /**
   * Проверяет возможность носить эту вещь.
   *
   * @return null, если вещь носить можно, либо SystemMessage, который можно показать игроку
   */
  public static final IStaticPacket checkIfCanEquip(Player player, ItemInstance item) {
    // FIXME [G1ta0] черезмерный хардкод, переделать на условия
    int itemId = item.getItemId();
    int targetSlot = item.getTemplate().getBodyPart();
    Clan clan = player.getClan();

    // TODO: [Bonux] проверить, могут ли носить Камаэли щиты и сигили R ранга.
    if (!player.getClassId().isOfLevel(ClassLevel.AWAKED)
        && item.getGrade() != ItemGrade.R
        && item.getGrade() != ItemGrade.R95
        && item.getGrade() != ItemGrade.R99) {
      // камаэли и хеви/робы/щиты/сигилы
      if (player.getRace() == Race.KAMAEL
          && (item.getItemType() == ArmorType.HEAVY
              || item.getItemType() == ArmorType.MAGIC
              || item.getItemType() == ArmorType.SIGIL
              || item.getItemType() == WeaponType.NONE))
        return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;

      // не камаэли и рапиры/арбалеты/древние мечи
      if (player.getRace() != Race.KAMAEL
          && (item.getItemType() == WeaponType.CROSSBOW
              || item.getItemType() == WeaponType.RAPIER
              || item.getItemType() == WeaponType.ANCIENTSWORD))
        return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;
    }

    if (itemId >= 7850 && itemId <= 7859 && player.getLvlJoinedAcademy() == 0) // Clan Oath Armor
    return SystemMsg.THIS_ITEM_CAN_ONLY_BE_WORN_BY_A_MEMBER_OF_THE_CLAN_ACADEMY;

    if (isClanApellaItem(itemId) && player.getPledgeRank().ordinal() < PledgeRank.WISEMAN.ordinal())
      return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;

    if (item.getItemType() == WeaponType.DUALDAGGER
        && player.getSkillLevel(923) < 1
        && player.getSkillLevel(10502) < 1)
      return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;

    // Корона лидера клана, владеющего замком
    if (itemId == 6841 && (clan == null || !player.isClanLeader() || clan.getCastle() == 0))
      return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;

    // Нельзя одевать оружие, если уже одето проклятое оружие. Проверка двумя способами, для
    // надежности.
    if (targetSlot == ItemTemplate.SLOT_LR_HAND
        || targetSlot == ItemTemplate.SLOT_L_HAND
        || targetSlot == ItemTemplate.SLOT_R_HAND) {
      if (itemId != player.getInventory().getPaperdollItemId(Inventory.PAPERDOLL_RHAND)
          && CursedWeaponsManager.getInstance()
              .isCursed(player.getInventory().getPaperdollItemId(Inventory.PAPERDOLL_RHAND)))
        return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;
      if (player.isCursedWeaponEquipped() && itemId != player.getCursedWeaponEquippedId())
        return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;
    }

    // Плащи
    if (item.getTemplate().isCloak()) {
      // Can be worn by Knights or higher ranks who own castle
      if (item.getName().contains("Knight")
          && (player.getPledgeRank().ordinal() < PledgeRank.KNIGHT.ordinal()
              || player.getCastle() == null))
        return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;

      // Плащи для камаэлей
      if (item.getName().contains("Kamael") && player.getRace() != Race.KAMAEL)
        return SystemMsg.YOU_DO_NOT_MEET_THE_REQUIRED_CONDITION_TO_EQUIP_THAT_ITEM;

      // Плащи можно носить только с S80 или S84 сетом
      if (!player.getOpenCloak())
        return SystemMsg.THE_CLOAK_CANNOT_BE_EQUIPPED_BECAUSE_YOUR_ARMOR_SET_IS_NOT_COMPLETE;
    }

    if (targetSlot == ItemTemplate.SLOT_DECO) {
      int count = player.getTalismanCount();
      if (count <= 0)
        return new SystemMessage2(
                SystemMsg.YOU_CANNOT_WEAR_S1_BECAUSE_YOU_ARE_NOT_WEARING_A_BRACELET)
            .addItemName(itemId);

      ItemInstance deco;
      for (int slot = Inventory.PAPERDOLL_DECO1; slot <= Inventory.PAPERDOLL_DECO6; slot++) {
        deco = player.getInventory().getPaperdollItem(slot);
        if (deco != null) {
          if (deco == item) return null; // талисман уже одет и количество слотов больше нуля
          // Проверяем на количество слотов и одинаковые талисманы
          if (--count <= 0 || deco.getItemId() == itemId)
            return new SystemMessage2(
                    SystemMsg.YOU_CANNOT_EQUIP_S1_BECAUSE_YOU_DO_NOT_HAVE_ANY_AVAILABLE_SLOTS)
                .addItemName(itemId);
        }
      }
    }
    return null;
  }