Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Lineage II (https://forum.zone-game.info/forumdisplay.php?f=34)
-   -   [share] Поддержка самопальных заточек в фениксе (https://forum.zone-game.info/showthread.php?t=17000)

Gaikotsu 05.12.2011 12:58

[share] Поддержка самопальных заточек в фениксе
 
Выкладываю простенький класс для феникса, для поддержки самопальных свитков заточки (например поддержки свитков для заточки посоха в эвенте 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 - все равно это будет после всего этого мертвым кодом.

З.Ы. и да, просьба к определенным личностям не тырить шару и не продавать ее потом как свою "собственноручно написанную разработку, которую вы можете купить только у нас" - намек думаю понятно кому адресован :)

KilRoy 05.12.2011 13:41

Re: [share] Поддержка самопальных заточек в фениксе
 
Цитата:

Сообщение от Gaikotsu (Сообщение 150839)
З.Ы. и да, просьба к определенным личностям не тырить шару и не продавать ее потом как свою "собственноручно написанную разработку, которую вы можете купить только у нас" - намек думаю понятно кому адресован

Чётко под-убрал :)))


Текущее время: 11:24. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot