Cycle 390-399 focus : Stabilization, quests end. Changeset 398 (2308) is up ! Admin commands - part II, Petition, TradeList, TargetHandler, Community Manager, Olympiads, Formulas, Bugfixes, Organization

UseItem exploit fix (duplicate items) - ALL L2J VERSIONS

Tryskell · 1 · 3236

Offline Tryskell

  • The cute dwarf
  • *
    • Posts: 4.123

The video was produced using my pack (or so state the server owner/developer), but L2J got the same issue. All non-customized L2J versions using WeaponEquipTask got this issue. Even if you patched other places to avoid to get multiple similar items with same objectId, this is the initial problem and the only fix you should apply.

For the goodness of L2J, I decided to post this fix for free.

Short version : Upon UseItem use, and if you're currently attacking, WeaponEquipTask is called to delay the time your weapon is wear.

Issue : There is no check upon task call. The item is equipped, no matter what happened between the call time, and the wear time (if you deleted, crystallized, dropped, put item elsewhere,...).

Fix : check upon task call if the item is still existing on inventory.

For L2J (consider to edit the called method - remove item parameter).

Code: [Select]
   /** Weapon Equip Task */
    private static class WeaponEquipTask implements Runnable
        private final L2PcInstance activeChar;
        protected WeaponEquipTask(L2PcInstance character)
            activeChar = character;
        public void run()
            // Check if the item is still on inventory.
            final ItemInstance item = activeChar.getInventory().getItemByObjectId(_objectId);
            if (item == null)
            // Equip or unEquip
            activeChar.useEquippableItem(item, false);

If you use aCis, here's the modified task found on UseItem (will be part of rev 380) :

Code: [Select]
			if (activeChar.isAttackingNow())
ThreadPool.schedule(() -> {
final ItemInstance itemToTest = activeChar.getInventory().getItemByObjectId(_objectId);
if(itemToTest == null)

activeChar.useEquippableItem(itemToTest, false);
}, activeChar.getAttackEndTime() - System.currentTimeMillis());
activeChar.useEquippableItem(item, true);

Good luck everyone !  :clap:
Code: [Select]
Triskel does not speak with foolish fellows who do not know their profession!