Не отображается описание аугментации

  • Автор темы Автор темы Psycho
  • Дата начала Дата начала

Psycho

Легенда
Кто в курсе, из-за чего может не отображаться описание аугментации на предмете?
Хроники хф. Протокол 542.
Камни вставляются/снимаются.

Screenshot_4.webp Screenshot_5.webp
 
в серверных пакетах связанных с отправкой инфы о предметах (ItemList, InventoryUpdate и т.п.), а точнее без конкретизации сборки не могу сказать.

еще кстати может не того типа идшники ауг шлешь.
к примеру в хф это hh, а после уже dd. и вроде еще в самых новых хрониках вобще 3 ид шлются, а не 2 (но это неточно).
 
Последнее редактирование:
в серверных пакетах, а точнее без конкретизации сборки не могу сказать.

еще кстати может не того типа идшники ауг шлешь.
к примеру в хф это hh, а после уже dd. и вроде еще в самых новых хрониках вобще 3 ид шлются, а не 2 (но это неточно).
Ну в RequestRefine я убрал лишние int и long, и добавил readByte как в 542, чтобы камни вставлялись.

Java:
package org.l2jmobius.gameserver.network.clientpackets;

import org.l2jmobius.gameserver.data.AugmentationData;
import org.l2jmobius.gameserver.model.Augmentation;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.item.enums.ItemProcessType;
import org.l2jmobius.gameserver.model.item.instance.Item;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.enums.StatusUpdateType;
import org.l2jmobius.gameserver.network.serverpackets.ExVariationResult;
import org.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
import org.l2jmobius.gameserver.network.serverpackets.StatusUpdate;

/**
 * @author -Wooden-
 */
public class RequestRefine extends AbstractRefinePacket
{
    private int _targetItemObjId;
    private int _refinerItemObjId;
    private int _gemStoneItemObjId;
    private long _gemStoneCount;
   
    @Override
    protected void readImpl()
    {
        _targetItemObjId = readInt();
        _refinerItemObjId = readInt();
        readByte();
    }
   
    @Override
    protected void runImpl()
    {
        final Player player = getPlayer();
        if (player == null)
        {
            return;
        }
       
        final Item targetItem = player.getInventory().getItemByObjectId(_targetItemObjId);
        if (targetItem == null)
        {
            return;
        }
       
        final Item refinerItem = player.getInventory().getItemByObjectId(_refinerItemObjId);
        if (refinerItem == null)
        {
            return;
        }
       
        final Item gemStoneItem = player.getInventory().getItemByObjectId(_gemStoneItemObjId);
        if (gemStoneItem == null)
        {
            return;
        }
       
        if (!isValid(player, targetItem, refinerItem, gemStoneItem))
        {
            player.sendPacket(new ExVariationResult(0, 0, 0));
            player.sendPacket(SystemMessageId.AUGMENTATION_FAILED_DUE_TO_INAPPROPRIATE_CONDITIONS);
            return;
        }
       
        final LifeStone ls = getLifeStone(refinerItem.getId());
        if (ls == null)
        {
            return;
        }
       
        final int lifeStoneLevel = ls.getLevel();
        final int lifeStoneGrade = ls.getGrade();
        if (_gemStoneCount != getGemStoneCount(targetItem.getTemplate().getCrystalType(), lifeStoneGrade))
        {
            player.sendPacket(new ExVariationResult(0, 0, 0));
            player.sendPacket(SystemMessageId.AUGMENTATION_FAILED_DUE_TO_INAPPROPRIATE_CONDITIONS);
            return;
        }
       
        // unequip item
        if (targetItem.isEquipped())
        {
            final InventoryUpdate iu = new InventoryUpdate();
            for (Item itm : player.getInventory().unEquipItemInSlotAndRecord(targetItem.getLocationSlot()))
            {
                iu.addModifiedItem(itm);
            }
           
            player.sendPacket(iu); // Sent inventory update for unequip instantly.
            player.broadcastUserInfo();
        }
       
        // consume the life stone
        if (!player.destroyItem(ItemProcessType.FEE, refinerItem, 1, null, false))
        {
            return;
        }
       
        // consume the gemstones
        if (!player.destroyItem(ItemProcessType.FEE, gemStoneItem, _gemStoneCount, null, false))
        {
            return;
        }
       
        final Augmentation aug = AugmentationData.getInstance().generateRandomAugmentation(lifeStoneLevel, lifeStoneGrade, targetItem.getTemplate().getBodyPart(), refinerItem.getId(), targetItem);
        targetItem.setAugmentation(aug);
       
        final int stat12 = 0x0000FFFF & aug.getAugmentationId();
        final int stat34 = aug.getAugmentationId() >> 16;
        player.sendPacket(new ExVariationResult(stat12, stat34, 1));
       
        final InventoryUpdate iu = new InventoryUpdate();
        iu.addModifiedItem(targetItem);
        player.sendPacket(iu); // Sent inventory update for destruction instantly.
       
        final StatusUpdate su = new StatusUpdate(player);
        su.addUpdate(StatusUpdateType.CUR_LOAD, player.getCurrentLoad());
        player.sendPacket(su);
    }
}
Всё остальное по дефолту от хф.
 
ну финальная ауга у тебя точно криво формируется
не нужно тут делать битовые операции с ид опций - просто послать как есть 2 int значения их в пакетах
То-есть надо слать типо вот такого, как в 542?
Java:
        // Only reuse old options for slots that are truly optional and intentionally left empty (if needed).
        // For your rare group, we don't fallback to old augment.
        final int option1 = augment.getOption1Id();
        final int option2 = augment.getOption2Id();
        final int option3 = augment.getOption3Id();
      
        // Optional: only fallback for option1/2 if your design requires at least 2 guaranteed options.
        final VariationInstance oldAugment = targetItem.getAugmentation();
        if (oldAugment != null)
        {
            final int newOption1 = (option1 > 0) ? option1 : 0;
            final int newOption2 = (option2 > 0) ? option2 : 0;
            final int newOption3 = (option3 > 0) ? option3 : 0; // Do not fallback to old 3rd option.
            augment = new VariationInstance(augment.getMineralId(), newOption1, newOption2, newOption3);
        }
        player.sendPacket(new ExVariationResult(augment.getOption1Id(), augment.getOption2Id(), augment.getOption3Id(), true));

Вместо вот этого?
Java:
        final int stat12 = 0x0000FFFF & aug.getAugmentationId();
        final int stat34 = aug.getAugmentationId() >> 16;
        player.sendPacket(new ExVariationResult(stat12, stat34, 1));
 
тут еще надо посмотреть что у тебя там в итоге generateRandomAugmentation выдает и уже от этого плясать

З.Ы. во многих старых сборках и правда фигней страдали и вместо того чтобы хранить и слать 2 short значения, упаковывали аугу в один int и хранили и слали его.
 
тут еще надо посмотреть что у тебя там в итоге generateRandomAugmentation выдает и уже от этого плясать
Ну по дефолту хф вот такое там
Java:
     /**
     * Generate a new random augmentation
     * @param lifeStoneLevel
     * @param lifeStoneGrade
     * @param bodyPart
     * @param lifeStoneId
     * @param targetItem
     * @return
     */
    public Augmentation generateRandomAugmentation(int lifeStoneLevel, int lifeStoneGrade, BodyPart bodyPart, int lifeStoneId, Item targetItem)
    {
        switch (bodyPart)
        {
            case BodyPart.LR_FINGER:
            case BodyPart.LR_EAR:
            case BodyPart.NECK:
            {
                return generateRandomAccessoryAugmentation(lifeStoneLevel, bodyPart, lifeStoneId);
            }
            default:
            {
                return generateRandomWeaponAugmentation(lifeStoneLevel, lifeStoneGrade, lifeStoneId, targetItem);
            }
        }
    }
 
    private Augmentation generateRandomWeaponAugmentation(int level, int lifeStoneGrade, int lifeStoneId, Item item)
    {
        int stat12 = 0;
        int stat34 = 0;
        if (PlayerConfig.RETAIL_LIKE_AUGMENTATION)
        {
            if (item.getTemplate().isMagicWeapon())
            {
                final List<AugmentationChance> selectedChances12 = new ArrayList<>();
                final List<AugmentationChance> selectedChances34 = new ArrayList<>();
                for (AugmentationChance ac : _augmentationChances)
                {
                    if (ac.getWeaponType().equals("mage") && (ac.getStoneId() == lifeStoneId))
                    {
                        if (ac.getVariationId() == 1)
                        {
                            selectedChances12.add(ac);
                        }
                        else
                        {
                            selectedChances34.add(ac);
                        }
                    }
                }
             
                int r = Rnd.get(10000);
                float s = 10000;
                for (AugmentationChance ac : selectedChances12)
                {
                    if (s > r)
                    {
                        s -= (ac.getAugmentChance() * 100);
                        stat12 = ac.getAugmentId();
                    }
                }
             
                int[] gradeChance = null;
                switch (lifeStoneGrade)
                {
                    case AbstractRefinePacket.GRADE_NONE:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
                        break;
                    }
                    case AbstractRefinePacket.GRADE_MID:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
                        break;
                    }
                    case AbstractRefinePacket.GRADE_HIGH:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
                        break;
                    }
                    case AbstractRefinePacket.GRADE_TOP:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
                        break;
                    }
                    default:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
                    }
                }
             
                int c = Rnd.get(100);
                if (c < gradeChance[0])
                {
                    c = 55;
                }
                else if (c < (gradeChance[0] + gradeChance[1]))
                {
                    c = 35;
                }
                else if (c < (gradeChance[0] + gradeChance[1] + gradeChance[2]))
                {
                    c = 7;
                }
                else
                {
                    c = 3;
                }
             
                final List<AugmentationChance> selectedChances34final = new ArrayList<>();
                for (AugmentationChance ac : selectedChances34)
                {
                    if (ac.getCategoryChance() == c)
                    {
                        selectedChances34final.add(ac);
                    }
                }
             
                r = Rnd.get(10000);
                s = 10000;
                for (AugmentationChance ac : selectedChances34final)
                {
                    if (s > r)
                    {
                        s -= (ac.getAugmentChance() * 100);
                        stat34 = ac.getAugmentId();
                    }
                }
            }
            else
            {
                final List<AugmentationChance> selectedChances12 = new ArrayList<>();
                final List<AugmentationChance> selectedChances34 = new ArrayList<>();
                for (AugmentationChance ac : _augmentationChances)
                {
                    if (ac.getWeaponType().equals("warrior") && (ac.getStoneId() == lifeStoneId))
                    {
                        if (ac.getVariationId() == 1)
                        {
                            selectedChances12.add(ac);
                        }
                        else
                        {
                            selectedChances34.add(ac);
                        }
                    }
                }
             
                int r = Rnd.get(10000);
                float s = 10000;
                for (AugmentationChance ac : selectedChances12)
                {
                    if (s > r)
                    {
                        s -= (ac.getAugmentChance() * 100);
                        stat12 = ac.getAugmentId();
                    }
                }
             
                int[] gradeChance = null;
                switch (lifeStoneGrade)
                {
                    case AbstractRefinePacket.GRADE_NONE:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
                        break;
                    }
                    case AbstractRefinePacket.GRADE_MID:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_MID_CHANCE;
                        break;
                    }
                    case AbstractRefinePacket.GRADE_HIGH:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_HIGH_CHANCE;
                        break;
                    }
                    case AbstractRefinePacket.GRADE_TOP:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_TOP_CHANCE;
                        break;
                    }
                    default:
                    {
                        gradeChance = PlayerConfig.RETAIL_LIKE_AUGMENTATION_NG_CHANCE;
                    }
                }
             
                int c = Rnd.get(100);
                if (c < gradeChance[0])
                {
                    c = 55;
                }
                else if (c < (gradeChance[0] + gradeChance[1]))
                {
                    c = 35;
                }
                else if (c < (gradeChance[0] + gradeChance[1] + gradeChance[2]))
                {
                    c = 7;
                }
                else
                {
                    c = 3;
                }
             
                final List<AugmentationChance> selectedChances34final = new ArrayList<>();
                for (AugmentationChance ac : selectedChances34)
                {
                    if (ac.getCategoryChance() == c)
                    {
                        selectedChances34final.add(ac);
                    }
                }
             
                r = Rnd.get(10000);
                s = 10000;
                for (AugmentationChance ac : selectedChances34final)
                {
                    if (s > r)
                    {
                        s -= (ac.getAugmentChance() * 100);
                        stat34 = ac.getAugmentId();
                    }
                }
            }
         
            return new Augmentation(((stat34 << 16) + stat12));
        }
Сообщение объединено:
А в 542 вот такое
Java:
     /**
     * Generates a new random variation instance based on the specified variation template.
     * <p>
     * This method creates a {@link VariationInstance} by selecting random effects for the given variation and applying it to the specified target item.
     * </p>
     * @param variation the {@link Variation} template from which the instance will be generated
     * @param targetItem the {@link Item} on which the variation will be applied
     * @return a new {@link VariationInstance} with random effects
     */
    public VariationInstance generateRandomVariation(Variation variation, Item targetItem)
    {
        return generateRandomVariation(variation, targetItem.getId());
    }
 
    /**
     * Generates a new random variation instance based on the specified variation template and target item ID.
     * <p>
     * This private method is a helper that generates a {@link VariationInstance} by selecting random effects based on the target item ID.
     * </p>
     * @param variation the {@link Variation} template from which the instance will be generated
     * @param targetItemId the ID of the item on which the variation will be applied
     * @return a new {@link VariationInstance} with random effects
     */
    private VariationInstance generateRandomVariation(Variation variation, int targetItemId)
    {
        final Options option1 = variation.getRandomEffect(0, targetItemId);
        final Options option2 = variation.getRandomEffect(1, targetItemId);
        final Options option3 = variation.getRandomEffect(2, targetItemId);
        return new VariationInstance(variation.getMineralId(), option1, option2, option3);
    }
 
какой п...ц :)
ты где такую древность выкопал?
по моему уже во всех вменяемых сборках этот допотопный п..ц с такой генерацией ауг выпилили давно.
 
Ну вот тебе теперь надо слать 3 ид опций, ну или хотя бы в последней слать 0, если надо только данные от 2 опций в ауге показывать как в хф.
т.е. вобщем 3 int слать в качестве инфы об ауге

Ну в любом случае тебе лучше пытать тех кто колупает именно последние протоколы - я то пишу это все чисто теоретически, ибо сам все так же потихоньку мучаю уже старенький 286 протокол :)
 
Ну вот тебе теперь надо слать 3 ид опций, ну или хотя бы в последней слать 0, если надо только данные от 2 опций в ауге показывать как в хф.
т.е. вобщем 3 int слать в качестве инфы об ауге

Ну в любом случае тебе лучше пытать тех кто колупает именно последние протоколы - я то пишу это все чисто теоретически, ибо сам все так же потихоньку мучаю уже старенький 286 протокол :)
Я думаю там не сильно система аугмента различается между 286 и 542
 
Ну у меня шлютстся просто 2 инта в блоке инфы об ауге, вот в целом и всей разницы.

Java:
    protected void writeItem(ItemInfo item, long count, int mask)
    {
        writeH(mask);
        writeD(item.getObjectId());
        writeD(item.getTemplate().getId());
        writeC(item.getEquipSlot());
        writeQ(count);
        writeC(item.getTemplate().getType2ForPackets()); // тип предмета: 00-weapon, 01-shield/armor, 02-ring/earring/necklace, 03-questitem, 04-adena, 05-item
        writeC(item.getCustomType1()); // всегда 0
        writeH(item.isEquipped());
        writeQ(item.getTemplate().getBodyPartSlot()); // слот для эквипа
        writeH(item.getEnchantLevel()); // уровень заточки (уровень пета, если это предмет для его призыва)
        writeC(item.getCustomType2()); // 0 - пет с стандартным именем (имя NPC), 1 - пет с именем, заданным игроком
        writeD(item.getRemainingDurationTime());
        writeD(item.getAppearanceId() == 0 ? item.getRemainingPeriodTime() : item.getAppearanceTimeForPackets()); // оставшееся время жизни для временного предмета/временной внешки
        writeC(item.isUseable());
        writeH(item.isLocked());

        if (containsMask(mask, ItemListType.AUGMENTATION_OPTIONS))
            writeItemAugment(item);

        if (containsMask(mask, ItemListType.ELEMENTAL_ATTRIBUTE))
            writeItemElemental(item);

        if (containsMask(mask, ItemListType.ENCHANT_OPTIONS))
            writeItemEnchantEffect(item);

        if (containsMask(mask, ItemListType.APPEARANCE))
            writeD(item.getAppearanceId());

        if (containsMask(mask, ItemListType.ENSOUL_OPTIONS))
            writeItemEnsoulOptions(item);

        if (containsMask(mask, ItemListType.USE_COUNT))
            writeH(item.getCurrentUseCount());

        if (containsMask(mask, ItemListType.REUSE_DELAY))
            writeD(item.getCurrentReuse());

        if (containsMask(mask, ItemListType.PET_DATA))
            writePetData(item);

        if (containsMask(mask, ItemListType.BLESS_OPTION))
            writeC(1);
    }

    protected static final int calculateMask(ItemInfo item)
    {
        int mask = 0;

        if (!item.getAugmentation().equals(AugmentationData.EMPTY))
            mask |= ItemListType.AUGMENTATION_OPTIONS.getMask();

        if (item.getAttackAttribute() != AttributeType.NONE || item.checkDefenceAttributeValues())
            mask |= ItemListType.ELEMENTAL_ATTRIBUTE.getMask();

        if (item.getEnchantOptions() != null)
            for (int id : item.getEnchantOptions())
                if (id > 0)
                {
                    mask |= ItemListType.ENCHANT_OPTIONS.getMask();
                    break;
                }

        if (item.getAppearanceId() > 0)
            mask |= ItemListType.APPEARANCE.getMask();

        if (item.getEnsoulOptions(EnsoulType.NORMAL).size() > 0 || item.getEnsoulOptions(EnsoulType.SPECIAL).size() > 0)
            mask |= ItemListType.ENSOUL_OPTIONS.getMask();

        if (item.getMaxUseCount() > 0)
        {
            mask |= ItemListType.USE_COUNT.getMask();

            if (item.getCurrentReuse() > 0)
                mask |= ItemListType.REUSE_DELAY.getMask();
        }

        if (item.isBlessed())
            mask |= ItemListType.BLESS_OPTION.getMask();

        return mask;
    }

    protected void writeItemAugment(AugmentationData data)
    {
        writeD(data.getOption1Id());
        writeD(data.getOption2Id());
    }

    protected void writeItemAugment(ItemInfo item)
    {
        writeItemAugment(item != null ? item.getAugmentation() : AugmentationData.EMPTY);
    }

    protected void writeItemAugment(MultiSellItem item)
    {
        writeItemAugment(item != null ? item.getAugmentation() : AugmentationData.EMPTY);
    }

З.Ы. А вобще зря ты за основу взял хф мобиуса - мало того там код древний, так та еще какашка.
даже чистый овер 2012-2013 годов был бы лучшим вариантом для последующего допила и адаптации к новым клиентам.
 
Ну у меня шлютстся просто 2 инта в блоке инфы об ауге, вот в целом и всей разницы.

Java:
    protected void writeItem(ItemInfo item, long count, int mask)
    {
        writeH(mask);
        writeD(item.getObjectId());
        writeD(item.getTemplate().getId());
        writeC(item.getEquipSlot());
        writeQ(count);
        writeC(item.getTemplate().getType2ForPackets()); // тип предмета: 00-weapon, 01-shield/armor, 02-ring/earring/necklace, 03-questitem, 04-adena, 05-item
        writeC(item.getCustomType1()); // всегда 0
        writeH(item.isEquipped());
        writeQ(item.getTemplate().getBodyPartSlot()); // слот для эквипа
        writeH(item.getEnchantLevel()); // уровень заточки (уровень пета, если это предмет для его призыва)
        writeC(item.getCustomType2()); // 0 - пет с стандартным именем (имя NPC), 1 - пет с именем, заданным игроком
        writeD(item.getRemainingDurationTime());
        writeD(item.getAppearanceId() == 0 ? item.getRemainingPeriodTime() : item.getAppearanceTimeForPackets()); // оставшееся время жизни для временного предмета/временной внешки
        writeC(item.isUseable());
        writeH(item.isLocked());

        if (containsMask(mask, ItemListType.AUGMENTATION_OPTIONS))
            writeItemAugment(item);

        if (containsMask(mask, ItemListType.ELEMENTAL_ATTRIBUTE))
            writeItemElemental(item);

        if (containsMask(mask, ItemListType.ENCHANT_OPTIONS))
            writeItemEnchantEffect(item);

        if (containsMask(mask, ItemListType.APPEARANCE))
            writeD(item.getAppearanceId());

        if (containsMask(mask, ItemListType.ENSOUL_OPTIONS))
            writeItemEnsoulOptions(item);

        if (containsMask(mask, ItemListType.USE_COUNT))
            writeH(item.getCurrentUseCount());

        if (containsMask(mask, ItemListType.REUSE_DELAY))
            writeD(item.getCurrentReuse());

        if (containsMask(mask, ItemListType.PET_DATA))
            writePetData(item);

        if (containsMask(mask, ItemListType.BLESS_OPTION))
            writeC(1);
    }

    protected static final int calculateMask(ItemInfo item)
    {
        int mask = 0;

        if (!item.getAugmentation().equals(AugmentationData.EMPTY))
            mask |= ItemListType.AUGMENTATION_OPTIONS.getMask();

        if (item.getAttackAttribute() != AttributeType.NONE || item.checkDefenceAttributeValues())
            mask |= ItemListType.ELEMENTAL_ATTRIBUTE.getMask();

        if (item.getEnchantOptions() != null)
            for (int id : item.getEnchantOptions())
                if (id > 0)
                {
                    mask |= ItemListType.ENCHANT_OPTIONS.getMask();
                    break;
                }

        if (item.getAppearanceId() > 0)
            mask |= ItemListType.APPEARANCE.getMask();

        if (item.getEnsoulOptions(EnsoulType.NORMAL).size() > 0 || item.getEnsoulOptions(EnsoulType.SPECIAL).size() > 0)
            mask |= ItemListType.ENSOUL_OPTIONS.getMask();

        if (item.getMaxUseCount() > 0)
        {
            mask |= ItemListType.USE_COUNT.getMask();

            if (item.getCurrentReuse() > 0)
                mask |= ItemListType.REUSE_DELAY.getMask();
        }

        if (item.isBlessed())
            mask |= ItemListType.BLESS_OPTION.getMask();

        return mask;
    }

    protected void writeItemAugment(AugmentationData data)
    {
        writeD(data.getOption1Id());
        writeD(data.getOption2Id());
    }

    protected void writeItemAugment(ItemInfo item)
    {
        writeItemAugment(item != null ? item.getAugmentation() : AugmentationData.EMPTY);
    }

    protected void writeItemAugment(MultiSellItem item)
    {
        writeItemAugment(item != null ? item.getAugmentation() : AugmentationData.EMPTY);
    }

З.Ы. А вобще зря ты за основу взял хф мобиуса - мало того там код древний, так та еще какашка.
даже чистый овер 2012-2013 годов был бы лучшим вариантом для последующего допила и адаптации к новым клиентам.
А что на счет лостов? Я еще их просто время от времени ковыряю, но пока на только на клиенте хф.
 
ну лосты, если речь про лостворлд, и есть по сути овер, просто более свежей версии, так сказать.

З.Ы. У меня в основе серва кстати тоже овер, если что. Правда за прошедшие годы уже капитально перелопаченный и во многом уже даже близко не похожий на первоисточник :)
 
Последнее редактирование:
Назад
Сверху Снизу