How to work with Extractable Items aka Capsule Items

Path: gameserver/data/capsule_items.xml

1. File structure - capsule_items.xml

XML:
<?xml version="1.0" encoding="UTF-8"?>
<list>
    <!-- Example 1: Regular box with equal chances -->
    <capsule itemId="22000" consume="true">
        <item id="22006" min="3" max="3" chance="20.55555" />
        <item id="22007" min="2" max="2" chance="14.01515" />
        <item id="22008" min="1" max="1" chance="6.16666" />
        <!-- ... other items ... -->
        <item id="22025" min="5" max="5" chance="12.77777" />
    </capsule>

    <!-- Example 2: Premium version of the same box -->
    <capsule itemId="22001" consume="true">
        <item id="22007" min="3" max="3" chance="27.27272" />
        <!-- Premium rewards (only for players with active Premium Account) -->
        <premium_item id="8749" min="1" max="1" chance="15" />
        <premium_item id="8750" min="1" max="1" chance="15" />
    </capsule>

    <!-- Example 3: Requires an item to open -->
    <capsule itemId="9599" requiredItemId="9600" requiredItemAmount="1" consume="true">
        <item id="9600" min="1" max="2" chance="4" />
        <item id="9601" min="1" max="2" chance="10" />
        <item id="9602" min="1" max="1" chance="1" />
    </capsule>

    <!-- Example 4: Pre-enchanted items -->
    <capsule itemId="21799" consume="true">
        <item id="21793" min="1" max="1" enchant_min="0" enchant_max="0" chance="100" />
        <item id="21794" min="1" max="1" enchant_min="0" enchant_max="0" chance="100" />
        <!-- all set pieces -->
    </capsule>
</list>

2. Full list of attributes
For <capsule> tag:
  • itemId - capsule ID (required)
  • requiredItemId - ID of item required to open (0 = none)
  • requiredItemAmount - amount of required item
  • consume="true|false" - destroy capsule after use (default true)
For <item> and <premium_item> tags:
  • id - reward item ID
  • min / max - quantity (if min=max - fixed amount)
  • chance - chance in percent (up to 5 decimal places, total ≤ 100.00)
  • enchant_min / enchant_max - enchant level (if min=max - fixed, otherwise random range)
Important notes:
  • Only ONE random item drops from the <item> + <premium_item> list (or nothing if total chance < 100%).
  • All items with chance="100" drop 100% of the time (guaranteed rewards).
  • Premium rewards work only for players with active Premium Account (hasBonus()).

3. How to add a new box
  1. Open gameserver/data/capsule_items.xml
  2. Add new <capsule itemId="YOUR_ID"> block
  3. Fill <item> and optional <premium_item> tags
  4. Save file
  5. Restart server
 
Last edited:
It is possible to add multiple items drop from 1 capsule?
For example open capsule item id=70000
and after open capsure drop
item id=9990 chance 100%
item id=9991 chance 100%
item id=9992 chance 100%
item id=9993 chance 100%
 
In high five and some other chronicles i've seen for example:
Newbie gift (item)
double click this item and recive full no grade equipment, and some consumables
is possible?
 
In high five and some other chronicles i've seen for example:
Newbie gift (item)
double click this item and recive full no grade equipment, and some consumables
is possible?
Of course, mother of god
Example:
<capsule itemId="capsule_id">
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="consumable_id" min="1" max="1" chance="100." />
<item id="consumable_id" min="1" max="1" chance="100." />
<item id="consumable_id" min="1" max="1" chance="100." />
</capsule>
 
Is there a way to make a capsule open with a certain level?

If not, could you add that option please?
 
Is it possible to spawn a mob with capsule?
Like
<capsule itemId="8534">
<npcid="20004" min="1" max="1" chance="100." />
</capsule>
no is not, you can write extension for spawn NPC from item.
For example:

Spawn NpcId 20001 on Use item 100500 and spawn 20002 on use item 100501
also you can add check zones and etc etc etc.
Code:
package handler.items;

import l2.gameserver.model.Player;
import l2.gameserver.model.items.ItemInstance;
import l2.gameserver.utils.NpcUtils;

public class SpawnNpcItem extends SimpleItemHandler
{
    private static final int[] ITEM_IDS = new int[] { 100500, 100501 };

    @Override
    public int[] getItemIds()
    {
        return ITEM_IDS;
    }

    @Override
    protected boolean useItemImpl(Player player, ItemInstance item, boolean ctrl)
    {
        int itemId = item.getItemId();
      
        if(!useItem(player, item, 1))
            return false;
      
        switch(itemId)
        {
            case 100500:
                NpcUtils.spawnSingle(20001, player.getLoc(), 120000L);
                break;
            case 100501:
                NpcUtils.spawnSingle(20002, player.getLoc(), 120000L);
                break;
            default:
                return false;
        }

        return true;
    }
}
 
Last edited:
Of course, mother of god
Example:
<capsule itemId="capsule_id">
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="equip_id" min="1" max="1" chance="100." />
<item id="consumable_id" min="1" max="1" chance="100." />
<item id="consumable_id" min="1" max="1" chance="100." />
<item id="consumable_id" min="1" max="1" chance="100." />
</capsule>
Hola estoy recien empezando, como seria para frozen ya que la mayoría esta así
8483;6912,18,30;6914,4,22;8351,7,17;8375,1,5;8378,1,24;-1,0,2
 
no is not, you can write extension for spawn NPC from item.
For example:

Spawn NpcId 20001 on Use item 100500 and spawn 20002 on use item 100501
also you can add check zones and etc etc etc.
Code:
package handler.items;

import l2.gameserver.model.Player;
import l2.gameserver.model.items.ItemInstance;
import l2.gameserver.utils.NpcUtils;

public class SpawnNpcItem extends SimpleItemHandler
{
    private static final int[] ITEM_IDS = new int[] { 100500, 100501 };

    @Override
    public int[] getItemIds()
    {
        return ITEM_IDS;
    }

    @Override
    protected boolean useItemImpl(Player player, ItemInstance item, boolean ctrl)
    {
        int itemId = item.getItemId();
     
        if(!useItem(player, item, 1))
            return false;
     
        switch(itemId)
        {
            case 100500:
                NpcUtils.spawnSingle(20001, player.getLoc(), 120000L);
                break;
            case 100501:
                NpcUtils.spawnSingle(20002, player.getLoc(), 120000L);
                break;
            default:
                return false;
        }

        return true;
    }
}
How do I place a config that added the id and boss, outside of core?
 
Actualmente he creado una caja, pero cuando la abro solo da 1 artículo de varios que tengo actualmente. Comparto el xml de la cápsula. Quiero que generes al menos 3 elementos por cada vez que se abra la caja.
<capsule itemId="9362"><!-- Cofre Mid -->
<item id="9344" min="1" max="1" chance="80.55" /><!-- L2LS - Wild Walk Buff -->
<item id="9343" min="1" max="1" chance="80.55" /><!-- L2LS - Wild Magic Buff -->
<item id="9342" min="1" max="1" chance="80.55" /><!-- L2LS - Mejora de ira vampírica -->
<item id="9341" min="1" max="1" chance="80.55" /><!-- L2LS - Shield Buff -->
<item id="5965" min="20" max="20" chance="80.30" /><!-- Blank Scroll -->
<item id="6392" min="20" max="20" chance="80.30" /><!-- Medalla del evento -->

<item id="5550" min="20" max="20" chance="50.55" /><!-- Placa de metal duradera -->
<item id="4042" min="20" max="20" chance="50.55" /><!-- Enria -->
<item id="5549" min="20" max="20" chance="50.55" /><!-- Hilo metálico -->
<item id="4044" min="20" max="20" chance="50.55" /><!-- Thons -->
<item id="1865" min="20" max="20" chance="50.55" /><!-- Barniz -->
<item id="9310" min="1" max="1" chance="50.55" /><!-- Kamaloca Pass -->
<item id="9345" min="1" max="1" chance="50.55" /><!-- Runa Adena 24hs -->
<item id="9346" min="1" max="1" chance="50.55" /><!-- Runa Drop 24hs -->
<item id="9347" min="1" max="1" chance="50.55" /><!-- Runa Experiencia 24hs -->
<item id="9348" min="1" max="1" chance="50.55" /><!-- Runa Spoil 24hs -->

<item id="1894" min="20" max="20" chance="20.55" /><!-- Cuero artesanal ********* -->
<item id="1876", min="20", max="20", chance="20.55" /><!-- Mineral de Mithril ********* -->
<item id="4039" min="20" max="20" chance="20.55" /><!-- ********* de pegamento para moldes -->
<item id="2148" min="1" max="1" chance="20.55" /><!-- Receta:Cuero artesanal ********* -->
</cápsula>
 
hi i can create one scrip to exchange x item for random items, and he remove all items "x", dont see where is error can help me?


package custom;

import l2.commons.util.Rnd;
import l2.gameserver.model.instances.NpcInstance;
import l2.gameserver.model.quest.Quest;
import l2.gameserver.model.quest.QuestState;
import l2.gameserver.scripts.ScriptFile;

public class _900_CofreMid extends Quest implements ScriptFile {

public static final int[] Runa24Hs = new int[] { 9345, 9346, 9347, 9348 };

public static final int[] Runa10Dias = new int[] { 9349, 9350, 9351, 9352 };

public static final int[] Skines = new int[] { 9496, 9497, 9498, 9499, 9500, 9501, 9502, 9503, 9504, 9505, 9506 };

public static final int[] Dyes = new int[] { 7002, 70003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, 7013 };

public static final int[] SoulCrystal12 = new int[] { 5577, 5578, 5579 };

public static final int[] SoulCrystal13 = new int[] { 5580, 5581, 5582 };

public static final int[] CofreID = new int[] { 9361, 9362, 9363 };


public _900_CofreMid() {
super(1);
addStartNpc(60000);
}

public void onLoad() {System.out.println("Probando Fix Cofres------------====---------()");}

public void onReload() {}

public void onShutdown() {}

public String onEvent(String paramString, QuestState paramQuestState, NpcInstance paramNpcInstance)
{
String str = paramString;
int i = paramNpcInstance.getNpcId();

if (paramString.equalsIgnoreCase("reply_1"))
{
switch (i)
{
case 60000:
if (paramQuestState.getQuestItemsCount(9361) >= 1L)
{

int k = Rnd.get(10);

if (k == 1) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(728, 20L);
paramQuestState.takeItems(9361, -1L);
}

if (k == 2) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(726, 20L);
paramQuestState.takeItems(9361, -1L);
break;

}

if (k == 3) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(Runa24Hs[Rnd.get(Runa24Hs.length)], 1L);
paramQuestState.takeItems(9361, -1L);
break;

}


if (k == 4) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(5965, 20L);
paramQuestState.takeItems(9361, -1L);
break;
}

if (k == 5) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(5951, 20L);
paramQuestState.takeItems(9361, -1L);
break;

}

if (k == 6) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(3874, 1L);
paramQuestState.takeItems(9361, -1L);
break;
}

if (k == 7) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(9313, 5L);
paramQuestState.takeItems(9361, -1L);
break;

}

if (k == 8) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(2148, 1L);
paramQuestState.takeItems(9361, -1L);
break;

}

if (k == 9) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(9366, 2L);
paramQuestState.takeItems(9361, -1L);
break;
}


if (k == 10) {
str = "low-manapotion.htm";
paramQuestState.playSound("ItemSound.quest_finish");
paramQuestState.giveItems(9365, 2L);
paramQuestState.takeItems(9361, -1L);
break;
}
}
}


}

else if (paramString.equalsIgnoreCase("reply_2"))
{

paramQuestState.takeItems(9362, -1L);
switch (i)

{
case 60000:
if (paramQuestState.getQuestItemsCount(9362) >= 1L)
{

int k = Rnd.get(10);

if (k == 1) {
paramQuestState.giveItems(Skines[Rnd.get(Skines.length)], 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 2) {
paramQuestState.giveItems(Dyes[Rnd.get(Dyes.length)], 10L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 3) {
paramQuestState.giveItems(728, 20L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 4) {
paramQuestState.giveItems(4198, 1L);
paramQuestState.giveItems(4120, 15L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 5) {
paramQuestState.giveItems(4193, 2L);
paramQuestState.giveItems(4115, 13L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 6) {
paramQuestState.giveItems(9308, 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 7) {
paramQuestState.giveItems(8297, 2L);
paramQuestState.giveItems(8330, 13L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 8) {
paramQuestState.giveItems(8305, 2L);
paramQuestState.giveItems(8336, 13L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 9) {
paramQuestState.giveItems(4199, 2L);
paramQuestState.giveItems(4121, 13L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 10) {
paramQuestState.giveItems(4192, 2L);
paramQuestState.giveItems(4114, 13L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

}

break;
}
}



else if (paramString.equalsIgnoreCase("reply_3"))
{

paramQuestState.takeItems(9363, -1L);

switch (i)
{
case 60000:
if (paramQuestState.getQuestItemsCount(9363) >= 1L)
{
int k = Rnd.get(3);

if (k == 1) {
paramQuestState.giveItems(9367, 2L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 2) {
paramQuestState.giveItems(Skines[Rnd.get(Skines.length)], 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 3) {
paramQuestState.giveItems(Runa10Dias[Rnd.get(Runa10Dias.length)], 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 5) {
paramQuestState.giveItems(6013, 200L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 6) {
paramQuestState.giveItems(6012, 50L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 7) {
paramQuestState.giveItems(4673, 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 8) {
paramQuestState.giveItems(SoulCrystal12[Rnd.get(SoulCrystal12.length)], 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}

if (k == 9) {
paramQuestState.giveItems(SoulCrystal13[Rnd.get(SoulCrystal12.length)], 1L);
paramQuestState.playSound("ItemSound.quest_finish");

break;
}
}

break;
}
}

return str;
}

public String onTalk(NpcInstance paramNpcInstance, QuestState paramQuestState)
{
String str = "no-quest";
int j = paramNpcInstance.getNpcId();

if (j == 60000)
{
if (paramQuestState.getQuestItemsCount(CofreID) == 0L)
{
str = "no-item.htm";
}

if (paramQuestState.getQuestItemsCount(CofreID) != 0L)
{
str = "dindin_q0688_01.htm";

}
}

return str;
}

}
 
Back
Top