U3Games

Games | Desarrollo & Soporte => L2 | Sección de Servidores => Lineage => L2 | Implementaciones => Mensaje iniciado por: Jerry en Ago 02, 2025, 02:14 PM

Título: Black Coupon Essence - Interlude
Publicado por: Jerry en Ago 02, 2025, 02:14 PM
el sql

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50740
Source Host           : localhost:3306
Source Database       : l2j

Target Server Type    : MYSQL
Target Server Version : 50740
File Encoding         : 65001

Date: 2023-06-19 14:40:34
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for item_recover
-- ----------------------------
DROP TABLE IF EXISTS `item_recover`;
CREATE TABLE `item_recover` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `object_id` int(11) NOT NULL,
  `item_id` int(11) NOT NULL,
  `item_name` varchar(255) DEFAULT NULL,
  `enchant_level` int(11) NOT NULL,
  `item_type` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `object_id_index` (`object_id`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1;



### Eclipse Workspace Patch 1.0
#P OrionRev28

diff --git src/l2jorion/game/handler/ItemHandler.java src/l2jorion/game/handler/ItemHandler.java
index d009bbf..8eec4e5 100644
--- src/l2jorion/game/handler/ItemHandler.java
+++ src/l2jorion/game/handler/ItemHandler.java
@@ -23,7 +23,6 @@
 import l2jorion.game.handler.item.ClanSkillsCustomItem;
 import l2jorion.game.handler.item.CrystalCarol;
 import l2jorion.game.handler.item.Crystals;
-import l2jorion.game.handler.item.CustomAugmentationSystem;
 import l2jorion.game.handler.item.CustomItemForFighter;
 import l2jorion.game.handler.item.CustomItemForMage;
 import l2jorion.game.handler.item.CustomPotions;
@@ -40,6 +39,7 @@
 import l2jorion.game.handler.item.HeroCustom365DaysItem;
 import l2jorion.game.handler.item.HeroCustom7DaysItem;
 import l2jorion.game.handler.item.HsItems;
+import l2jorion.game.handler.item.Item_Recover;
 import l2jorion.game.handler.item.JackpotSeed;
 import l2jorion.game.handler.item.MOSKey;
 import l2jorion.game.handler.item.MapForestOfTheDead;
@@ -133,6 +133,7 @@
  registerItemHandler(new BreakingArrow());
  registerItemHandler(new ChristmasTree());
  registerItemHandler(new Crystals());
+ registerItemHandler(new Item_Recover());
  registerItemHandler(new HsItems());
  registerItemHandler(new ClanPointCustomItem());
  registerItemHandler(new ClanSkillsCustomItem());


diff --git files/game/config/main/L2jOrion.ini files/game/config/main/L2jOrion.ini
index 32991a0..97ef069 100644
--- files/game/config/main/L2jOrion.ini
+++ files/game/config/main/L2jOrion.ini
@@ -503,3 +503,11 @@
 # ItemId
 # Format: Id,min,max,chance;Id,min,max,chance
 GlobalDropItem = 3470,10,15,100
+
+
+#==========================================================================
+#   BLACK COUPON RECOVERY 1 ITEM ENCHANT FAILED
+#==========================================================================
+
+BlackCouponId = 6392
+
diff --git src/Base/Data/IconTable.java src/Base/Data/IconTable.java
new file mode 100644
index 0000000..fdce5d7
--- /dev/null
+++ src/Base/Data/IconTable.java
@@ -0,0 +1,62 @@
+package Base.Data;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class IconTable extends XMLDocument
+{
+ private static final Map<Integer, String> itemIcons = new HashMap<>();
+
+ public IconTable()
+ {
+ load();
+ }
+
+ @Override
+ protected void load()
+ {
+ loadDocument("./data/xml/icons.xml");
+ LOG.info("Loaded " + itemIcons.size() + " icons.");
+ }
+
+ @Override
+ protected void parseDocument(Document doc, File f)
+ {
+ // First element is never read.
+ final Node n = doc.getFirstChild();
+
+ for (Node o = n.getFirstChild(); o != null; o = o.getNextSibling())
+ {
+ if (!"icon".equalsIgnoreCase(o.getNodeName()))
+ {
+ continue;
+ }
+
+ final NamedNodeMap attrs = o.getAttributes();
+ final int itemId = Integer.valueOf(attrs.getNamedItem("Id").getNodeValue());
+ final String value = String.valueOf(attrs.getNamedItem("value").getNodeValue());
+
+ itemIcons.put(itemId, value);
+ }
+ }
+
+ public String getIcon(int id)
+ {
+ return itemIcons.get(id) == null ? "icon.noimage" : itemIcons.get(id);
+ }
+
+ public static IconTable getInstance()
+ {
+ return SingletonHolder._instance;
+ }
+
+ private static class SingletonHolder
+ {
+ protected static final IconTable _instance = new IconTable();
+ }
+}
diff --git src/Base/Data/XMLDocument.java src/Base/Data/XMLDocument.java
new file mode 100644
index 0000000..476a41d
--- /dev/null
+++ src/Base/Data/XMLDocument.java
@@ -0,0 +1,119 @@
+package Base.Data;
+
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import l2jorion.game.templates.StatsSet;
+
+/**
+ * An XML document, relying on a static and single DocumentBuilderFactory.
+ */
+public abstract class XMLDocument
+{
+ protected static final Logger LOG = Logger.getLogger(XMLDocument.class.getName());
+
+ protected Document document;
+
+ private static final DocumentBuilderFactory BUILDER;
+ static
+ {
+ BUILDER = DocumentBuilderFactory.newInstance();
+ BUILDER.setValidating(false);
+ BUILDER.setIgnoringComments(true);
+ }
+
+ abstract protected void load();
+
+ abstract protected void parseDocument(Document doc, File f);
+
+ public void loadDocument(String filePath)
+ {
+ loadDocument(new File(filePath));
+ }
+
+ public void writeDocument(Document doc, String fileName)
+ {
+ try
+ {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+ DOMSource source = new DOMSource(doc);
+ StreamResult result = new StreamResult(new File(fileName));
+
+ transformer.transform(source, result);
+ LOG.info("XML file saved to " + fileName);
+ }
+ catch (TransformerException e)
+ {
+ LOG.warning("Error saving XML file: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Parse an entire directory or file if found.
+ * @param file
+ */
+ public void loadDocument(File file)
+ {
+ if (!file.exists())
+ {
+ LOG.severe("The following file or directory doesn't exist: " + file.getName());
+ return;
+ }
+
+ if (file.isDirectory())
+ {
+ for (File f : file.listFiles())
+ {
+ loadDocument(f);
+ }
+ }
+ else if (file.isFile())
+ {
+ try
+ {
+ parseDocument(BUILDER.newDocumentBuilder().parse(file), file);
+ }
+ catch (Exception e)
+ {
+ LOG.log(Level.SEVERE, "Error loading XML file " + file.getName(), e);
+ }
+ }
+ }
+
+ public Document getDocument()
+ {
+ return document;
+ }
+
+ /**
+ * This method parses the content of a NamedNodeMap and feed the given StatsSet.
+ * @param attrs : The NamedNodeMap to parse.
+ * @param set : The StatsSet to feed.
+ */
+ public static void parseAndFeed(NamedNodeMap attrs, StatsSet set)
+ {
+ for (int i = 0; i < attrs.getLength(); i++)
+ {
+ final Node attr = attrs.item(i);
+ set.set(attr.getNodeName(), attr.getNodeValue());
+ }
+ }
+}
diff --git src/Base/RecoverySystem/ItemRecoveryManager.java src/Base/RecoverySystem/ItemRecoveryManager.java
new file mode 100644
index 0000000..d6448d1
--- /dev/null
+++ src/Base/RecoverySystem/ItemRecoveryManager.java
@@ -0,0 +1,271 @@
+package Base.RecoverySystem;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import l2jorion.Config;
+import l2jorion.game.datatables.sql.ItemTable;
+import l2jorion.game.model.actor.instance.L2ItemInstance;
+import l2jorion.game.model.actor.instance.L2PcInstance;
+import l2jorion.game.network.serverpackets.ItemList;
+import l2jorion.util.database.L2DatabaseFactory;
+
+public class ItemRecoveryManager
+{
+ private Map<Integer, Integer> validEnchantLevels; // Almacena los niveles de enchant válidos para cada artículo recuperable
+
+ public ItemRecoveryManager()
+ {
+ validEnchantLevels = new HashMap<>();
+ loadValidEnchantLevels(); // Carga los niveles de enchant válidos desde la base de datos o cualquier otra fuente de datos
+ }
+
+ public void recoverSelectedItem(L2PcInstance player, int itemId, int enchantLevel)
+ {
+ // Comprueba si el jugador tiene suficientes items del ID 6392
+ L2ItemInstance recoveryItem = player.getInventory().getItemByItemId(Config.BLACK_COUPON_ID);
+ if (recoveryItem == null || recoveryItem.getCount() < 1)
+ {
+ player.sendMessage("No tienes suficientes items para recuperar este item.");
+ return;
+ }
+
+ // Verifica el nivel de enchant del item recuperable en la base de datos
+ if (!isValidEnchantLevel(itemId, enchantLevel, player.getObjectId()))
+ {
+ player.sendMessage("No puedes recuperar este item con ese nivel de enchant.");
+ return;
+ }
+
+ // Verifica que el artículo que se está recuperando coincide con el artículo original
+ if (!isValidRecoveryItem(itemId, player.getObjectId()))
+ {
+ player.sendMessage("No puedes recuperar este item.");
+ return;
+ }
+
+ // Crea el item a recuperar con el ID y enchantLevel proporcionados
+ L2ItemInstance recoveredItem = ItemTable.getInstance().createItem("RecoverItem", itemId, 1, player);
+ recoveredItem.setEnchantLevel(enchantLevel);
+
+ // Agrega el item recuperado al inventario del jugador
+ player.getInventory().addItem("RecoverItem", recoveredItem, player, player);
+
+ // Cobra 1 item del ID 6392
+ player.getInventory().destroyItemByItemId("RecoveryCost", Config.BLACK_COUPON_ID, 1, player, player);
+
+ // Elimina el item recuperado de la base de datos
+ removeRecoverableItem(itemId, player.getObjectId());
+
+ // Actualiza el inventario del jugador para que aparezca el item recuperado
+ player.sendPacket(new ItemList(player, true));
+
+ // Envía un mensaje al jugador con el nombre del item y su nivel de enchant
+ String itemName = recoveredItem.getItemName();
+ String message = "Has recuperado el item " + itemName;
+ if (enchantLevel > 0)
+ {
+ message += " +" + enchantLevel;
+ }
+ player.sendMessage(message);
+ }
+
+ public boolean isValidRecoveryItem(int itemId, int objectId)
+ {
+ Connection con = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "SELECT item_id FROM item_recover WHERE object_id = ? AND item_id = ?";
+ statement = con.prepareStatement(sql);
+ statement.setInt(1, objectId);
+ statement.setInt(2, itemId);
+ resultSet = statement.executeQuery();
+
+ return resultSet.next(); // Si hay un resultado, el artículo es válido
+
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al obtener el artículo recuperable de la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ if (resultSet != null)
+ {
+ resultSet.close();
+ }
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión a la base de datos
+ e.printStackTrace();
+ }
+ }
+
+ return false; // Si ocurre alguna excepción o no se encuentra el artículo, se considera inválido
+ }
+
+ public boolean isValidEnchantLevel(int itemId, int enchantLevel, int objectId)
+ {
+ Connection con = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "SELECT enchant_level FROM item_recover WHERE object_id = ? AND item_id = ?";
+ statement = con.prepareStatement(sql);
+ statement.setInt(1, objectId);
+ statement.setInt(2, itemId);
+ resultSet = statement.executeQuery();
+
+ if (resultSet.next())
+ {
+ int validEnchantLevel = resultSet.getInt("enchant_level");
+ return enchantLevel == validEnchantLevel;
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al obtener el nivel de enchant válido de la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ if (resultSet != null)
+ {
+ resultSet.close();
+ }
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión a la base de datos
+ e.printStackTrace();
+ }
+ }
+
+ return false;
+ }
+
+ public void removeRecoverableItem(int itemId, int objectId)
+ {
+ Connection con = null;
+ PreparedStatement statement = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "DELETE FROM item_recover WHERE item_id = ? AND object_id = ?";
+ statement = con.prepareStatement(sql);
+ statement.setInt(1, itemId);
+ statement.setInt(2, objectId);
+ statement.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al eliminar el item recuperable de la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión a la base de datos
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void loadValidEnchantLevels()
+ {
+ Connection con = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "SELECT item_id, enchant_level FROM item_recover";
+ statement = con.prepareStatement(sql);
+ resultSet = statement.executeQuery();
+
+ while (resultSet.next())
+ {
+ int itemId = resultSet.getInt("item_id");
+ int enchantLevel = resultSet.getInt("enchant_level");
+
+ validEnchantLevels.put(itemId, enchantLevel);
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al obtener los niveles de enchant válidos de la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ if (resultSet != null)
+ {
+ resultSet.close();
+ }
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión a la base de datos
+ e.printStackTrace();
+ }
+ }
+ }
+
+}
diff --git src/Base/RecoverySystem/RecoverableItem.java src/Base/RecoverySystem/RecoverableItem.java
new file mode 100644
index 0000000..22182f7
--- /dev/null
+++ src/Base/RecoverySystem/RecoverableItem.java
@@ -0,0 +1,111 @@
+package Base.RecoverySystem;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import l2jorion.game.datatables.sql.ItemTable;
+import l2jorion.game.templates.L2Item;
+import l2jorion.util.database.L2DatabaseFactory;
+
+public class RecoverableItem
+{
+ private int objectId;
+ private int itemId;
+ private String itemName;
+ private int enchantLevel;
+ private boolean selected; // New field for selection status
+
+ public RecoverableItem(int objectId, int itemId, String itemName, int enchantLevel)
+ {
+ this.objectId = objectId;
+ this.itemId = itemId;
+ this.itemName = itemName;
+ this.enchantLevel = enchantLevel;
+ this.selected = false; // Default selection status is false
+ }
+
+ public int getObjectId()
+ {
+ return objectId;
+ }
+
+ public int getItemId()
+ {
+ return itemId;
+ }
+
+ public String getItemName()
+ {
+ return itemName;
+ }
+
+ public int getEnchantLevel()
+ {
+ return enchantLevel;
+ }
+
+ public void saveBrokenItemInfo()
+ {
+ Connection con = null;
+ PreparedStatement statement = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "INSERT INTO item_recover (object_id, item_id, item_name, enchant_level) VALUES (?, ?, ?, ?)";
+ statement = con.prepareStatement(sql);
+ statement.setInt(1, objectId);
+ statement.setInt(2, itemId);
+ statement.setString(3, itemName);
+ statement.setInt(4, enchantLevel);
+ statement.execute();
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al guardar en la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ // Cierra la conexión y el statement
+ try
+ {
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public boolean isSelected()
+ {
+ return selected;
+ }
+
+ public void setSelected(boolean selected)
+ {
+ this.selected = selected;
+ }
+
+ public String getIcon()
+ {
+ return getItem().getIcon();
+ }
+
+ public L2Item getItem()
+ {
+ return ItemTable.getInstance().getTemplate(itemId);
+ }
+
+}
diff --git src/l2jorion/Config.java src/l2jorion/Config.java
index 922ad04..06bdba7 100644
--- src/l2jorion/Config.java
+++ src/l2jorion/Config.java
@@ -2528,6 +2528,8 @@
  public static List<Integer> GLOBAL_DROP_NPC_ID;
  public static List<RewardHolder> GLOBAL_REWARD_ITEM;
 
+ public static int BLACK_COUPON_ID;
+
  public static void loadL2jOrionConfig()
  {
  final String L2jOrion = ConfigLoader.L2jOrion_CONFIG_FILE;
@@ -2546,6 +2548,9 @@
  RED_SKY = Boolean.parseBoolean(L2jOrionSettings.getProperty("RedSky", "False"));
  FREE_TELEPORT_UNTIL = Integer.parseInt(L2jOrionSettings.getProperty("FreeTeleportUntil", "1"));
  REMOVAL_AUGMENTATION_FREE = Boolean.parseBoolean(L2jOrionSettings.getProperty("RemovalAugmentationFree", "False"));
+
+ BLACK_COUPON_ID = Integer.parseInt(L2jOrionSettings.getProperty("BlackCouponId", "6392"));
+
  ALLOW_FREIGHT_AUGMENTED = Boolean.parseBoolean(L2jOrionSettings.getProperty("AllowFreightAugmentedItem", "False"));
  ANNOUNCE_BOSS_UNDER_ATTACK = Boolean.parseBoolean(L2jOrionSettings.getProperty("AnnounceBossUnderAttack", "False"));
  LIVE_CASTING_CHECK = Boolean.parseBoolean(L2jOrionSettings.getProperty("LiveCastingCheck", "False"));
diff --git src/l2jorion/game/GameServer.java src/l2jorion/game/GameServer.java
index 52faa7e..543cccd 100644
--- src/l2jorion/game/GameServer.java
+++ src/l2jorion/game/GameServer.java
@@ -11,6 +11,7 @@
 import java.util.Date;
 import java.util.logging.LogManager;
 
+import Base.Data.IconTable;
 import l2jorion.Config;
 import l2jorion.ConfigLoader;
 import l2jorion.ServerType;
@@ -495,6 +496,8 @@
  VoicedCommandHandler.getInstance();
  CommunityBoardManager.getInstance();
 
+ IconTable.getInstance();
+
  LOG.info("AutoChatHandler: Loaded " + AutoChatHandler.getInstance().size() + " handlers");
  LOG.info("AutoSpawnHandler: Loaded " + AutoSpawn.getInstance().size() + " handlers");
 
diff --git src/l2jorion/game/handler/item/Item_Recover.java src/l2jorion/game/handler/item/Item_Recover.java
new file mode 100644
index 0000000..2398bb3
--- /dev/null
+++ src/l2jorion/game/handler/item/Item_Recover.java
@@ -0,0 +1,175 @@
+package l2jorion.game.handler.item;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import Base.RecoverySystem.RecoverableItem;
+import l2jorion.Config;
+import l2jorion.game.handler.IItemHandler;
+import l2jorion.game.model.actor.instance.L2ItemInstance;
+import l2jorion.game.model.actor.instance.L2PcInstance;
+import l2jorion.game.model.actor.instance.L2PlayableInstance;
+import l2jorion.game.network.serverpackets.ActionFailed;
+import l2jorion.game.network.serverpackets.NpcHtmlMessage;
+import l2jorion.util.database.L2DatabaseFactory;
+
+/**
+ * @author Terius
+ */
+public class Item_Recover implements IItemHandler
+{
+ private static final int[] ITEM_IDS = new int[]
+ {
+ Config.BLACK_COUPON_ID
+ };
+
+ @Override
+ public void useItem(L2PlayableInstance playable, L2ItemInstance item)
+ {
+ if (!(playable instanceof L2PcInstance))
+ {
+ return;
+ }
+
+ L2PcInstance activeChar = (L2PcInstance) playable;
+
+ // Abre la ventana de recuperación y muestra los últimos 10 items recuperables
+ openRecoveryWindow(activeChar);
+ }
+
+ private static void openRecoveryWindow(L2PcInstance player)
+ {
+ // Obtén los últimos 10 items recuperables de la base de datos para el object_id del jugador
+ List<RecoverableItem> recoverableItems = getRecoverableItems(player.getObjectId());
+
+ // Verifica si hay items recuperables
+ if (recoverableItems.isEmpty())
+ {
+ // No hay items recuperables, muestra un mensaje al jugador
+ player.sendMessage("No hay items recuperables disponibles.");
+ return;
+ }
+
+ // Crea una instancia de NpcHtmlMessage para mostrar la ventana
+ NpcHtmlMessage html = new NpcHtmlMessage(1);
+
+ // Genera el contenido HTML de la ventana con la lista de los últimos 10 items recuperables
+ String content = generateRecoveryList(recoverableItems);
+ html.setHtml(content);
+
+ // Envía la ventana al jugador
+ player.sendPacket(html);
+ player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+
+ @Override
+ public int[] getItemIds()
+ {
+ return ITEM_IDS;
+ }
+
+ private static String generateRecoveryList(List<RecoverableItem> recoverableItems)
+ {
+
+ // Genera el contenido HTML de la ventana con la lista de los últimos 10 items recuperables
+ StringBuilder sb = new StringBuilder();
+ sb.append("<html><body><center><font color=\"LEVEL\">Items Recuperables</font><br><br>");
+
+ // Mensaje de advertencia sobre la recuperación de solo 1 item a la vez
+ sb.append("<font color=\"FF0000\">Solo puedes recuperar 1 item a la vez.</font><br>");
+
+ // Itera sobre los items recuperables
+ for (RecoverableItem item : recoverableItems)
+ {
+ sb.append("<img src=\"L2UI.SquareGray\" width=295 height=1>");
+ sb.append("<table>");
+
+ sb.append("<tr>");
+ sb.append("<td>");
+ sb.append("<img src=\"").append(item.getIcon()).append("\" width=32 height=32>");
+ sb.append("</td>");
+ sb.append("<td width=210><font color=\"FFFFFF\">").append(item.getItemName()).append("</font>");
+
+ int enchantLevel = item.getEnchantLevel();
+ if (enchantLevel > 0)
+ {
+ sb.append(" <font color=\"00FF00\">+").append(enchantLevel).append("</font>");
+ }
+
+ sb.append("</td>");
+
+ int itemId = item.getItemId();
+ sb.append("<td><button value=\"Recuperar\" action=\"bypass -h recoverSelectedItem ").append(itemId).append(" ").append(enchantLevel).append("\" width=75 height=21 back=\"L2UI.DefaultButton_click\" fore=\"L2UI.DefaultButton\"></td>");
+
+ sb.append("</tr>");
+
+ sb.append("</table>");
+ sb.append("<img src=\"L2UI.SquareGray\" width=295 height=1>");
+ sb.append("<br>"); // Agrega un espacio después de cada tabla
+ }
+
+ sb.append("</center></body></html>");
+ return sb.toString();
+ }
+
+ private static List<RecoverableItem> getRecoverableItems(int objectId)
+ {
+ List<RecoverableItem> recoverableItems = new ArrayList<>();
+ Connection con = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "SELECT item_id, item_name, enchant_level FROM item_recover WHERE object_id = ? ORDER BY id DESC LIMIT 10";
+ statement = con.prepareStatement(sql);
+ statement.setInt(1, objectId);
+ resultSet = statement.executeQuery();
+
+ while (resultSet.next())
+ {
+ int itemId = resultSet.getInt("item_id");
+ String itemName = resultSet.getString("item_name");
+ int enchantLevel = resultSet.getInt("enchant_level");
+
+ RecoverableItem item = new RecoverableItem(objectId, itemId, itemName, enchantLevel);
+ recoverableItems.add(item);
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al obtener los items recuperables de la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ if (resultSet != null)
+ {
+ resultSet.close();
+ }
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión a la base de datos
+ e.printStackTrace();
+ }
+ }
+
+ return recoverableItems;
+ }
+}
diff --git src/l2jorion/game/network/clientpackets/RequestBypassToServer.java src/l2jorion/game/network/clientpackets/RequestBypassToServer.java
index d48c078..88e85e4 100644
--- src/l2jorion/game/network/clientpackets/RequestBypassToServer.java
+++ src/l2jorion/game/network/clientpackets/RequestBypassToServer.java
@@ -26,6 +26,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import Base.RecoverySystem.ItemRecoveryManager;
 import javolution.text.TextBuilder;
 import l2jorion.Config;
 import l2jorion.game.cache.HtmCache;
@@ -592,6 +593,20 @@
  LOG.info(this.getClass().getSimpleName() + ": (" + activeChar.getName() + ") error: " + e);
  }
  }
+
+ else if (bp.bypass.startsWith("recoverSelectedItem"))
+ {
+ String[] bypassParts = bp.bypass.split(" ");
+ if (bypassParts.length >= 3)
+ {
+ int itemId = Integer.parseInt(bypassParts[1]);
+ int enchantLevel = Integer.parseInt(bypassParts[2]);
+
+ ItemRecoveryManager itemRecoveryManager = new ItemRecoveryManager();
+ itemRecoveryManager.recoverSelectedItem(activeChar, itemId, enchantLevel);
+ }
+ }
+
  else if (bp.bypass.equals("Draw"))
  {
  L2Object object = activeChar.getTarget();
diff --git src/l2jorion/game/network/clientpackets/RequestEnchantItem.java src/l2jorion/game/network/clientpackets/RequestEnchantItem.java
index fb6a5cb..e775287 100644
--- src/l2jorion/game/network/clientpackets/RequestEnchantItem.java
+++ src/l2jorion/game/network/clientpackets/RequestEnchantItem.java
@@ -17,6 +17,10 @@
  */
 package l2jorion.game.network.clientpackets;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
 import l2jorion.Config;
 import l2jorion.game.datatables.xml.AugmentationData;
 import l2jorion.game.datatables.xml.AugmentationScrollData;
@@ -43,6 +47,7 @@
 import l2jorion.game.util.Util;
 import l2jorion.logger.Logger;
 import l2jorion.logger.LoggerFactory;
+import l2jorion.util.database.L2DatabaseFactory;
 import l2jorion.util.random.Rnd;
 
 public final class RequestEnchantItem extends PacketClient
@@ -826,6 +831,10 @@
  activeChar.sendPacket(sm);
  }
  activeChar.getAchievement().increase(AchType.ENCHANT_FAILED);
+
+ // Agrega el código para guardar la información del item roto en la tabla de la base de datos
+ saveBrokenItemInfo(activeChar.getObjectId(), item.getItemId(), item.getItemName(), item.getEnchantLevel(), item.getItem().getItemType().name());
+
  }
 
  if (!blessedScroll && !crystalScroll)
@@ -1077,6 +1086,50 @@
  }
  }
 
+ private void saveBrokenItemInfo(int objectId, int itemId, String itemName, int enchantLevel, String itemType)
+ {
+ Connection con = null;
+ PreparedStatement statement = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ String sql = "INSERT INTO item_recover (object_id, item_id, item_name, enchant_level, item_type) VALUES (?, ?, ?, ?, ?)";
+ statement = con.prepareStatement(sql);
+ statement.setInt(1, objectId);
+ statement.setInt(2, itemId);
+ statement.setString(3, itemName);
+ statement.setInt(4, enchantLevel);
+ statement.setString(5, itemType);
+ statement.execute();
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al guardar en la base de datos
+ e.printStackTrace();
+ }
+ finally
+ {
+ // Cierra la conexión y el statement
+ try
+ {
+ if (statement != null)
+ {
+ statement.close();
+ }
+ if (con != null)
+ {
+ con.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ // Manejo de excepciones en caso de error al cerrar la conexión
+ e.printStackTrace();
+ }
+ }
+ }
+
  @Override
  public String getType()
  {
diff --git src/l2jorion/game/templates/L2Item.java src/l2jorion/game/templates/L2Item.java
index 5a2ada5..2656f9b 100644
--- src/l2jorion/game/templates/L2Item.java
+++ src/l2jorion/game/templates/L2Item.java
@@ -27,6 +27,7 @@
 import java.util.List;
 import java.util.Map;
 
+import Base.Data.IconTable;
 import javolution.util.FastList;
 import l2jorion.Config;
 import l2jorion.game.datatables.sql.ItemTable;
@@ -591,4 +592,9 @@
  CloseUtil.close(con);
  }
  }
+
+ public String getIcon()
+ {
+ return IconTable.getInstance().getIcon(getItemId());
+ }
 }