Рейтинг темы:
  • 0 Голос(ов) - 0 в среднем
  • 1
  • 2
  • 3
  • 4
  • 5
[share] Поддержка самопальных заточек в фениксе
#1
Выкладываю простенький класс для феникса, для поддержки самопальных свитков заточки (например поддержки свитков для заточки посоха в эвенте Master of Enchanting или свитки для точения Olf's T-Shirt).

Изначально в пакетах заточки в фениксе имеется поддержка заточек посоха для эвента Master of Enchanting, можно и для других комбинаций добавить, но сами понимаете - код получается из-за всех этих условий жутко громоздким и нечитабельным.
Собственно из-за этого я где-то с месяц назад и набросал для своего удобства класс, который поддерживает неограниченное количество самопальных комбинаций "свиток + затачиваемые свитком вещи", не усложняет сильно серверные пакеты заточки и легко настраивается через датапак.

итак, вот сам класс (куда положить в ядре - видно по заголовку):
Код:
package l2p.gameserver.tables;

import java.io.File;
import java.util.HashMap;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import l2p.Config;
import l2p.extensions.multilang.CustomMessage;
import l2p.gameserver.cache.Msg;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.model.items.L2ItemInstance;
import l2p.gameserver.model.items.PcInventory;
import l2p.gameserver.serverpackets.EnchantResult;
import l2p.gameserver.serverpackets.ExPutEnchantTargetItemResult;
import l2p.gameserver.serverpackets.InventoryUpdate;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.tables.ItemTable;
import l2p.gameserver.tables.SkillTable;
import l2p.gameserver.templates.L2Item;
import l2p.util.GArray;
import l2p.util.Log;
import l2p.util.Rnd;
import l2p.util.XMLUtil;

public class EnchantScrollData
{
    private static final String xmlFile = "data/enchant_scrolls.xml";
    
    private static EnchantScrollData _instance;
    private static HashMap<Integer, ScrollData> _data = new HashMap<Integer, ScrollData>();
    private static Logger _log = Logger.getLogger(EnchantScrollData.class.getName());

    private static final class ScrollData
    {
        public int chance = 0;
        public int action_of_fail = 0;
        public int safe_enchant = 0;
        public int max_enchant = 0;
        public int premium_bonus = 0;
        public GArray<Integer> items = new GArray<Integer>();
    }

    public static EnchantScrollData getInstance()
    {
        if(_instance == null)
            _instance = new EnchantScrollData();
        return _instance;
    }

    public EnchantScrollData()
    {
        loadXml();
    }

    private void loadXml()
    {
        final File localFile = new File(xmlFile);
        if (!localFile.exists())
        {
            System.out.println("File '" + xmlFile + "' not found!");
            return;
        }
        Document localDocument = null;
        try
        {
            final DocumentBuilderFactory localDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
            localDocumentBuilderFactory.setValidating(false);
            localDocumentBuilderFactory.setIgnoringComments(true);
            localDocument = localDocumentBuilderFactory.newDocumentBuilder().parse(localFile);
        }
        catch (final Exception e)
        {
            e.printStackTrace();
        }
        try
        {
            parseXml(localDocument);
        }
        catch (final Exception e)
        {
            e.printStackTrace();
        }
    }

    private void parseXml(final Document doc)
    {
        for (Node il = doc.getFirstChild(); il != null; il = il.getNextSibling())
            if ("list".equalsIgnoreCase(il.getNodeName()))
                for (Node area = il.getFirstChild(); area != null; area = area.getNextSibling())
                {
                    if ("scroll".equalsIgnoreCase(area.getNodeName()))
                    {
                        ScrollData data = new ScrollData();
                        int scrollId = XMLUtil.getAttributeIntValue(area, "id", 0);
                        if (scrollId > 0 && ItemTable.getInstance().isExists(scrollId))
                        {
                            data.chance = XMLUtil.getAttributeIntValue(area, "chance", 66);
                            data.action_of_fail = XMLUtil.getAttributeIntValue(area, "action_of_fail", 0);
                            data.safe_enchant = XMLUtil.getAttributeIntValue(area, "safe_enchant", 3);
                            data.max_enchant = XMLUtil.getAttributeIntValue(area, "max_enchant", Config.ENCHANT_MAX);
                            data.premium_bonus = XMLUtil.getAttributeIntValue(area, "premium_bonus", 0);
                            String temp = XMLUtil.getAttributeValue(area, "item_to_enchant");
                            if (temp != null && !temp.isEmpty())
                            {
                                String items[] = temp.split(",");
                                for (String item : items)
                                {
                                    int itemId = Integer.parseInt(item);
                                    if (itemId > 0 && ItemTable.getInstance().isExists(itemId))
                                        data.items.add(itemId);
                                    else
                                        _log.warning("EnchantScrollData: Not found item for enchant with id = " + itemId + ", scroll id = " + scrollId);
                                }
                            }
                            if (data.items.size() == 0)
                                _log.warning("EnchantScrollData: not specified enchanting items for scroll with id = " + scrollId);
                            else
                                _data.put(scrollId, data);
                        }
                        else
                            _log.warning("EnchantScrollData: Not found scroll with id = " + scrollId);
                    }
                }
        _log.info("EnchantScrollData: Loaded " + _data.size() + " custom enchant scrolls.");
    }

    public boolean requestEnchantItem(L2Player player, PcInventory inventory, L2ItemInstance scroll, L2ItemInstance item)
    {
        if (player == null || scroll == null || item == null || !_data.containsKey(scroll.getItemId()))
            return false;

        ScrollData data = _data.get(scroll.getItemId());

        if (!data.items.contains(item.getItemId()))
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendPacket(Msg.INAPPROPRIATE_ENCHANT_CONDITIONS);
            player.sendActionFailed();
            return true;
        }

        if (item.getLocation() != L2ItemInstance.ItemLocation.INVENTORY && item.getLocation() != L2ItemInstance.ItemLocation.PAPERDOLL)
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendPacket(Msg.INAPPROPRIATE_ENCHANT_CONDITIONS);
            player.sendActionFailed();
            return true;
        }

        if (player.getPrivateStoreType() != L2Player.STORE_PRIVATE_NONE)
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendPacket(Msg.YOU_CANNOT_PRACTICE_ENCHANTING_WHILE_OPERATING_A_PRIVATE_STORE_OR_PRIVATE_MANUFACTURING_WORKSHOP);
            player.sendActionFailed();
            return true;
        }

        if (item.isStackable() || (scroll = inventory.getItemByObjectId(scroll.getObjectId())) == null)
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendActionFailed();
            return true;
        }

        if (item.getOwnerId() != player.getObjectId())
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendPacket(Msg.INAPPROPRIATE_ENCHANT_CONDITIONS);
            player.sendActionFailed();
            return true;
        }

        if (item.getEnchantLevel() >= data.max_enchant)
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendMessage(new CustomMessage("l2p.gameserver.clientpackets.RequestEnchantItem.MaxLevel", player));
            player.sendActionFailed();
            return true;
        }

        L2ItemInstance removedScroll = null;
        synchronized (inventory)
        {
            removedScroll = inventory.destroyItem(scroll, 1, true);
        }

        if (removedScroll == null)
        {
            player.sendPacket(EnchantResult.CANCEL);
            player.sendActionFailed();
            return true;
        }

        int itemType = item.getItem().getType2();
        double chance = item.getEnchantLevel() < data.safe_enchant ? 100 : data.chance;
        
        if (data.premium_bonus > 0 && player.getNetConnection().getBonus() > 1)
            chance += data.premium_bonus;
        
        chance = Math.min(chance, 100D);

        Log.add(player.getName() + "|Trying to enchant|" + item.getItemId() + "|+" + item.getEnchantLevel() + "|" + item.getObjectId(), "enchants");

        if (Rnd.chance(chance))
        {
            item.setEnchantLevel(item.getEnchantLevel() + 1);
            item.updateDatabase();
            player.sendPacket(new InventoryUpdate().addModifiedItem(item));
            Log.add(player.getName() + "|Successfully enchanted|" + item.getItemId() + "|to+" + item.getEnchantLevel() + "|" + chance, "enchants");
            Log.LogItem(player, Log.EnchantItem, item);
            player.sendPacket(EnchantResult.SUCESS);

            if (item.getEnchantLevel() >= (itemType == L2Item.TYPE2_WEAPON ? 6 : 5))
            {
                player.enableSkill(21006);
                player.altUseSkill(SkillTable.getInstance().getInfo(21006, 1), player);
                player.broadcastPacket(new SystemMessage(SystemMessage.C1_HAS_SUCCESSFULY_ENCHANTED_A__S2_S3).addName(player).addNumber(item.getEnchantLevel()).addItemName(item.getItemId()));
            }
        }
        else
        {
            Log.add(player.getName() + "|Failed to enchant|" + item.getItemId() + "|+" + item.getEnchantLevel() + "|" + chance, "enchants");

            if (data.action_of_fail == 0)
            {
                if (item.isEquipped())
                    inventory.unEquipItemInSlot(item.getEquipSlot());

                L2ItemInstance destroyedItem = inventory.destroyItem(item.getObjectId(), 1, true);
                if (destroyedItem == null)
                {
                    _log.warning("failed to destroy " + item.getObjectId() + " after unsuccessful enchant attempt by char " + player.getName());
                    player.sendActionFailed();
                    return true;
                }

                Log.LogItem(player, Log.EnchantItemFail, item);
                player.sendPacket(EnchantResult.FAILED_NO_CRYSTALS);
                player.refreshExpertisePenalty();
            }
            else if (data.action_of_fail == 1)
            {
                item.setEnchantLevel(0);
                player.sendPacket(new InventoryUpdate().addModifiedItem(item));
                player.sendPacket(Msg.FAILED_IN_BLESSED_ENCHANT_THE_ENCHANT_VALUE_OF_THE_ITEM_BECAME_0);
                player.sendPacket(EnchantResult.BLESSED_FAILED);
            }
            else if (data.action_of_fail == 2)
            {
                player.sendPacket(EnchantResult.ANCIENT_FAILED);
            }
        }

        player.refreshOverloaded();
        player.setEnchantScroll(null);
        player.sendChanges();
        return true;
    }

    public boolean requestExTryToPutEnchantTargetItem(L2Player player, PcInventory inventory, L2ItemInstance scroll, L2ItemInstance item)
    {
        if (player == null || scroll == null || item == null || !_data.containsKey(scroll.getItemId()))
            return false;

        ScrollData data = _data.get(scroll.getItemId());

        if (!data.items.contains(item.getItemId()))
        {
            player.sendActionFailed();
            player.sendPacket(Msg.INAPPROPRIATE_ENCHANT_CONDITIONS);
            return true;
        }

        if (item.isStackable())
        {
            player.sendActionFailed();
            player.sendPacket(Msg.DOES_NOT_FIT_STRENGTHENING_CONDITIONS_OF_THE_SCROLL);
            return true;
        }

        if (item.getLocation() != L2ItemInstance.ItemLocation.INVENTORY && item.getLocation() != L2ItemInstance.ItemLocation.PAPERDOLL)
        {
            player.sendActionFailed();
            player.sendPacket(Msg.INAPPROPRIATE_ENCHANT_CONDITIONS);
            return true;
        }

        if (player.getPrivateStoreType() != L2Player.STORE_PRIVATE_NONE)
        {
            player.sendPacket(new ExPutEnchantTargetItemResult(0, 0, 0));
            player.sendPacket(Msg.YOU_CANNOT_PRACTICE_ENCHANTING_WHILE_OPERATING_A_PRIVATE_STORE_OR_PRIVATE_MANUFACTURING_WORKSHOP);
            return true;
        }

        if ((scroll = inventory.getItemByObjectId(scroll.getObjectId())) == null)
        {
            player.setEnchantScroll(null);
            player.sendPacket(new ExPutEnchantTargetItemResult(0, 0, 0));
            return true;
        }

        if (item.getEnchantLevel() >= data.max_enchant)
        {
            player.sendActionFailed();
            player.sendMessage(new CustomMessage("l2p.gameserver.clientpackets.RequestEnchantItem.MaxLevel", player));
            return true;
        }

        if (item.getOwnerId() != player.getObjectId())
        {
            player.sendPacket(new ExPutEnchantTargetItemResult(0, 0, 0));
            return true;
        }

        Log.add(player.getName() + "|Trying to put enchant|" + item.getItemId() + "|+" + item.getEnchantLevel() + "|" + item.getObjectId(), "enchants");
        player.sendPacket(new ExPutEnchantTargetItemResult(1, 0, 0));
        return true;
    }
}

а в датапак кладем xml-файл с названием enchant_scrolls.xml и примерно с таким содержанием (как обявлять новые комбинации понятно из комментариев в начале):
Код:
<?xml version="1.0" encoding="utf-8"?>
<list>
    <!--
    Здесь перечислены нестандартные свитки заточек, используемые для заточки определенных предметов, в основном для эвентов.

    Параметры, которые можно задавать для свитков:
        id        - идентификатор свитка.
        chance        - шанс удачной заточки (по умолчанию равно 66).
        action_of_fail    - действие с затачиваемым предметом при неудачной заточке: 0 - удалить, 1 - обнулить заточку, 2 - оставить старую заточку (по умолчанию равно 0).
        safe_enchant    - до какого уровня заточка является безопасной (по умолчанию равно 3).
        max_enchant    - до скольки максимум можно точить этим свитком (по умолчанию берется стандартный максимум, указанный в конфигурации сервера).
        premium_bonus    - прибавка к шансу успешной заточки, если у игрока активен премиум аккаунт (по умолчанию равно 0).
        item_to_enchant    - идентиикатор предмета, который можно заточить этим свитком (можно указывать несколько предметов, перечисляя идентификаторы через запятую).

    Внимание! Свитки обязательно должны быть зарегистрированы как свитки заточки в хэндлере data/scripts/items/EnchantScrolls.java.
    -->
    <!-- Master Yogi's Scroll: Enchant Weapon -->
    <scroll id="13540" chance="66" action_of_fail="0" safe_enchant="3" max_enchant="23" premium_bonus="0" item_to_enchant="13539" />
    <!-- Olf's T-shirt Enchant Scroll -->
    <scroll id="21581" chance="66" action_of_fail="0" safe_enchant="3" max_enchant="9" premium_bonus="0" item_to_enchant="21580" />
    <!-- Blessed Olf's T-shirt Enchant Scroll -->
    <scroll id="21582" chance="66" action_of_fail="1" safe_enchant="3" max_enchant="9" premium_bonus="0" item_to_enchant="21580" />
    <!-- Blessed Olf's T-shirt Enchant Scroll [Event] -->
    <scroll id="21707" chance="66" action_of_fail="1" safe_enchant="3" max_enchant="9" premium_bonus="0" item_to_enchant="21706" />
</list>
Изменения, которые еще требуется сделать в ядре сервера:

Код:
GameServer.java:

Добавить в любое удобное место метода GameServer(), где вызываются остальные подобные классы, строку

EnchantScrollData.getInstance();
---------
RequestEnchantItem.java:

Добавить после строк

        if (!RequestExTryToPutEnchantSupportItem.checkCatalyst(itemToEnchant, catalyst))
            catalyst = null;

строки

        if (EnchantScrollData.getInstance().requestEnchantItem(activeChar, inventory, scroll, itemToEnchant))
            return;
---------
RequestExTryToPutEnchantTargetItem.java:

Добавить после строк

        if (itemToEnchant == null || scroll == null)
        {
            activeChar.sendPacket(new ExPutEnchantTargetItemResult(0, 0, 0));
            return;
        }

строки

        if (EnchantScrollData.getInstance().requestExTryToPutEnchantTargetItem(activeChar, inventory, scroll, itemToEnchant))
            return;
Ну и не забываем добавить в этих классах в импорты класс EnchantScrollData.

Так же стоит почистить пакеты RequestEnchantItem и RequestExTryToPutEnchantTargetItem от уже ненужных проверок на соответствие вещей на свиток и посох из эвента Master of Enchanting - все равно это будет после всего этого мертвым кодом.

З.Ы. и да, просьба к определенным личностям не тырить шару и не продавать ее потом как свою "собственноручно написанную разработку, которую вы можете купить только у нас" - намек думаю понятно кому адресован Smile
Ответ
#2
Gaikotsu;150839 Написал:З.Ы. и да, просьба к определенным личностям не тырить шару и не продавать ее потом как свою "собственноручно написанную разработку, которую вы можете купить только у нас" - намек думаю понятно кому адресован
Чётко под-убрал Smile))
Ответ


Возможно похожие темы ...
Тема Автор Ответы Просмотры Последний пост
  [Share] PTS Vanganth - Classic Interlude P110 zoumhs 0 1,541 05-13-2023, 05:04 PM
Последний пост: zoumhs
  Share Gracia Final Off Euro Deazer 424 256,289 07-10-2022, 07:20 PM
Последний пост: JIecTap
  [share] lin][info 2.3 [Lindvior] Gaikotsu 0 1,828 09-22-2017, 08:40 PM
Последний пост: Gaikotsu
  [share] Родильная Комната (Nursery) Gaikotsu 6 2,972 03-23-2017, 11:39 AM
Последний пост: Gaikotsu
  [Share] Silentium Interlude (Last source) Dеmon 77 20,343 12-10-2014, 01:01 AM
Последний пост: kingzor
  [EPIC SHARE] BBS Advanced Buffer OneThunder 9 3,620 04-28-2014, 11:35 AM
Последний пост: OneThunder
  Lf fandc share iRevive 0 1,226 02-16-2014, 07:19 AM
Последний пост: iRevive
  [Share] Storm Inside - R60 (13/07/2013) Masone 12 3,647 07-16-2013, 08:30 PM
Последний пост: Hotaka
  [Share] Silentium Interlude R57 (20.01.2013) Dеmon 3 1,827 01-20-2013, 06:55 PM
Последний пост: gorodetskiy
  [Share] Interlude - Silentium от 25.08.2012 Dеmon 4 2,565 08-25-2012, 09:07 PM
Последний пост: Dеmon

Перейти к форуму:


Пользователи, просматривающие эту тему: 1 Гость(ей)