diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/00000-00099.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/00000-00099.xml index e6fba3adec..756f232d08 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/00000-00099.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/00000-00099.xml @@ -398,9 +398,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/01300-01399.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/01300-01399.xml index 938dca7dd1..9c7c67be3b 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/01300-01399.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/01300-01399.xml @@ -749,9 +749,8 @@ - + - @@ -764,9 +763,8 @@ - + - @@ -779,9 +777,8 @@ - + - @@ -794,9 +791,8 @@ - + - @@ -809,9 +805,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/09600-09699.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/09600-09699.xml index 5023069c35..05fea0f14b 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/09600-09699.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/09600-09699.xml @@ -461,9 +461,8 @@ - + - @@ -474,9 +473,8 @@ - + - @@ -488,9 +486,8 @@ - + - @@ -502,9 +499,8 @@ - + - @@ -516,9 +512,8 @@ - + - @@ -530,9 +525,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/18500-18599.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/18500-18599.xml index e518e0686b..6d4f073c28 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/18500-18599.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/18500-18599.xml @@ -879,9 +879,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/19400-19499.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/19400-19499.xml index 53df60361b..e386d35760 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/19400-19499.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/19400-19499.xml @@ -607,9 +607,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22000-22099.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22000-22099.xml index 01a72a5abd..003b6ad535 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22000-22099.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22000-22099.xml @@ -1338,9 +1338,8 @@ - + - @@ -1355,9 +1354,8 @@ - + - @@ -1372,9 +1370,8 @@ - + - @@ -1389,9 +1386,8 @@ - + - @@ -1406,9 +1402,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22100-22199.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22100-22199.xml index f59c2edc59..d81f8961a6 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22100-22199.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/22100-22199.xml @@ -815,9 +815,8 @@ - + - @@ -832,9 +831,8 @@ - + - @@ -849,9 +847,8 @@ - + - @@ -866,9 +863,8 @@ - + - @@ -883,9 +879,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/30300-30399.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/30300-30399.xml index 0dc60fa9bd..5e1cf9b642 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/30300-30399.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/30300-30399.xml @@ -1328,9 +1328,8 @@ - + - @@ -1338,9 +1337,8 @@ - + - @@ -1348,9 +1346,8 @@ - + - @@ -1358,9 +1355,8 @@ - + - @@ -1368,9 +1364,8 @@ - + - @@ -1378,9 +1373,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/32200-32299.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/32200-32299.xml index 2f3a6b61da..4d379ddebf 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/32200-32299.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/32200-32299.xml @@ -922,9 +922,8 @@ - + - @@ -934,9 +933,8 @@ - + - @@ -947,9 +945,8 @@ - + - @@ -960,9 +957,8 @@ - + - @@ -973,9 +969,8 @@ - + - @@ -986,9 +981,8 @@ - + - @@ -999,9 +993,8 @@ - + - @@ -1012,9 +1005,8 @@ - + - @@ -1024,9 +1016,8 @@ - + - @@ -1037,9 +1028,8 @@ - + - @@ -1050,9 +1040,8 @@ - + - @@ -1063,9 +1052,8 @@ - + - @@ -1076,9 +1064,8 @@ - + - @@ -1089,9 +1076,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45400-45499.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45400-45499.xml index 9d3c537ef1..5a77e0dd97 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45400-45499.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45400-45499.xml @@ -269,7 +269,7 @@ - + @@ -281,7 +281,7 @@ - + diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45500-45599.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45500-45599.xml index f6a477761f..81594e457a 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45500-45599.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/45500-45599.xml @@ -1560,9 +1560,8 @@ - + - @@ -1577,9 +1576,8 @@ - + - @@ -1594,9 +1592,8 @@ - + - @@ -1611,9 +1608,8 @@ - + - @@ -1628,9 +1624,8 @@ - + - @@ -1645,9 +1640,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/80400-80499.xml b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/80400-80499.xml index 8b080cb617..daa4b51247 100644 --- a/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/80400-80499.xml +++ b/L2J_Mobius_8.0_Homunculus/dist/game/data/stats/items/80400-80499.xml @@ -450,9 +450,8 @@ - + - @@ -463,9 +462,8 @@ - + - diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/data/ItemTable.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/data/ItemTable.java index 0a0be13537..bf30b2162c 100644 --- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/data/ItemTable.java +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/data/ItemTable.java @@ -47,11 +47,14 @@ import org.l2jmobius.gameserver.model.actor.instance.EventMonsterInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.events.EventDispatcher; import org.l2jmobius.gameserver.model.events.impl.item.OnItemCreate; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.items.Armor; import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.util.DocumentItem; import org.l2jmobius.gameserver.util.GMAudit; @@ -194,6 +197,15 @@ public class ItemTable if (item instanceof EtcItem) { _etcItems.put(item.getId(), (EtcItem) item); + + if ((item.getItemType() == EtcItemType.ARROW) || (item.getItemType() == EtcItemType.BOLT)) + { + final List skills = item.getAllSkills(); + if (skills != null) + { + AmmunitionSkillList.add(skills); + } + } } else if (item instanceof Armor) { diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Creature.java index 4ecb85e742..0128305549 100644 --- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -1154,11 +1154,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe // Try to do what is expected by having more attack speed. // final int reuse = (int) (Formulas.calculateReuseTime(this, weaponItem) / (Math.max(1, _stat.getAttackSpeedMultiplier() - 1))); - // Consume arrows + // Consume ammunition. final Inventory inventory = getInventory(); if (inventory != null) { - inventory.reduceArrowCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); + inventory.reduceAmmunitionCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); } // Check if the Creature is a PlayerInstance diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index 8cc0df94e9..0621c22c34 100644 --- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -220,6 +220,7 @@ import org.l2jmobius.gameserver.model.holders.AutoPlaySettingsHolder; import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder; import org.l2jmobius.gameserver.model.holders.DamageTakenHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.MovieHolder; import org.l2jmobius.gameserver.model.holders.PlayerEventHolder; import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder; @@ -261,6 +262,7 @@ import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Siege; import org.l2jmobius.gameserver.model.skills.AbnormalType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.model.skills.BuffInfo; import org.l2jmobius.gameserver.model.skills.CommonSkill; import org.l2jmobius.gameserver.model.skills.Skill; @@ -725,6 +727,8 @@ public class PlayerInstance extends Playable private BroochJewel _activeRubyJewel = null; private BroochJewel _activeShappireJewel = null; + private int _lastAmmunitionId = 0; + /** Event parameters */ private PlayerEventHolder eventStatus = null; @@ -853,7 +857,7 @@ public class PlayerInstance extends Playable // Shared dualclass skills. private static final String KNOWN_DUAL_SKILLS_VAR = "KNOWN_DUAL_SKILLS"; - private static final int[] DUAL_CLASS_SKILLS = new int[] + private static final int[] DUAL_CLASS_SKILLS = { 19222, // Dignity of the Exalted 19223, // Belief of the Exalted @@ -4439,20 +4443,6 @@ public class PlayerInstance extends Playable else { addItem("Pickup", target, null, true); - // Auto-Equip arrows/bolts if player has a bow/crossbow and player picks up arrows/bolts. - final ItemInstance weapon = _inventory.getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItem etcItem = target.getEtcItem(); - if (etcItem != null) - { - final EtcItemType itemType = etcItem.getItemType(); - if (((weapon.getItemType() == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) || (((weapon.getItemType() == WeaponType.CROSSBOW) || (weapon.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) - { - checkAndEquipAmmunition(itemType); - } - } - } } } } @@ -5772,33 +5762,85 @@ public class PlayerInstance extends Playable @Override protected boolean checkAndEquipAmmunition(EtcItemType type) { - ItemInstance arrows = _inventory.getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if (arrows == null) + ItemInstance ammunition = null; + final Weapon weapon = getActiveWeaponItem(); + if (type == EtcItemType.ARROW) { - final Weapon weapon = getActiveWeaponItem(); - if (type == EtcItemType.ARROW) - { - arrows = _inventory.findArrowForBow(weapon); - } - else if (type == EtcItemType.BOLT) - { - arrows = _inventory.findBoltForCrossBow(weapon); - } - if (arrows != null) - { - // Equip arrows needed in left hand - _inventory.setPaperdollItem(Inventory.PAPERDOLL_LHAND, arrows); - sendItemList(); - return true; - } + ammunition = _inventory.findArrowForBow(weapon); } - else + else if (type == EtcItemType.BOLT) { + ammunition = _inventory.findBoltForCrossBow(weapon); + } + + if (ammunition != null) + { + addAmmunitionSkills(ammunition); + sendItemList(); return true; } + + removeAmmunitionSkills(); return false; } + private void addAmmunitionSkills(ItemInstance ammunition) + { + final int currentAmmunitionId = ammunition.getId(); + if (_lastAmmunitionId == currentAmmunitionId) + { + return; + } + removeAmmunitionSkills(); + _lastAmmunitionId = currentAmmunitionId; + + final List skills = ammunition.getItem().getAllSkills(); + if (skills == null) + { + return; + } + + boolean sendSkillList = false; + for (ItemSkillHolder holder : skills) + { + if (!isAffectedBySkill(holder)) + { + final Skill skill = holder.getSkill(); + if (skill.isPassive()) + { + addSkill(skill); + sendSkillList = true; + } + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + + public void removeAmmunitionSkills() + { + if (_lastAmmunitionId == 0) + { + return; + } + _lastAmmunitionId = 0; + + boolean sendSkillList = false; + for (Integer skillId : AmmunitionSkillList.values()) + { + if (removeSkill(skillId.intValue(), true) != null) + { + sendSkillList = true; + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + /** * Disarm the player's weapon. * @return {@code true} if the player was disarmed or doesn't have a weapon to disarm, {@code false} otherwise. diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java index 157c2d27ba..93a9cf3335 100644 --- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java @@ -53,14 +53,12 @@ import org.l2jmobius.gameserver.model.holders.AgathionSkillHolder; import org.l2jmobius.gameserver.model.holders.ArmorsetSkillHolder; import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder; -import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.appearance.AppearanceStone; import org.l2jmobius.gameserver.model.items.appearance.AppearanceType; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; import org.l2jmobius.gameserver.model.items.type.ArmorType; import org.l2jmobius.gameserver.model.items.type.EtcItemType; -import org.l2jmobius.gameserver.model.items.type.ItemType; import org.l2jmobius.gameserver.model.items.type.WeaponType; import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.SkillConditionScope; @@ -231,33 +229,50 @@ public abstract class Inventory extends ItemContainer @Override public void notifyUnequiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) + if ((slot != PAPERDOLL_RHAND) || !item.isWeapon()) { return; } - if (item.getItemType() == WeaponType.BOW) + switch (item.getWeaponItem().getItemType()) { - final ItemInstance arrow = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (arrow != null) + case BOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (bolts != null) + case CROSSBOW: + case TWOHANDCROSSBOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if (item.getItemType() == WeaponType.FISHINGROD) - { - final ItemInstance lure = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (lure != null) + case FISHINGROD: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (leftHandItem != null) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + break; } } } @@ -265,27 +280,6 @@ public abstract class Inventory extends ItemContainer @Override public void notifyEquiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) - { - return; - } - - if (item.getItemType() == WeaponType.BOW) - { - final ItemInstance arrow = inventory.findArrowForBow(item.getItem()); - if (arrow != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, arrow); - } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.findBoltForCrossBow(item.getItem()); - if (bolts != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, bolts); - } - } } } @@ -1847,24 +1841,6 @@ public abstract class Inventory extends ItemContainer return; } - // Equip only identical grade arrows. - final EtcItem etcItem = item.getEtcItem(); - if (etcItem != null) - { - final ItemInstance weapon = getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItemType itemType = etcItem.getItemType(); - final ItemType weaponItemType = weapon.getItemType(); - if ((((weaponItemType == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) // - || (((weaponItemType == WeaponType.CROSSBOW) || (weaponItemType == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) // - && (weapon.getItem().getCrystalTypePlus() != item.getItem().getCrystalTypePlus())) - { - return; - } - } - } - final PlayerInstance player = (PlayerInstance) getOwner(); if (!player.canOverrideCond(PlayerCondOverride.ITEM_CONDITIONS) && !player.isHero() && item.isHeroItem()) { @@ -1885,27 +1861,23 @@ public abstract class Inventory extends ItemContainer } } - // don't care about arrows, listener will unequip them (hopefully) // handle full armor // formal dress if (targetSlot == Item.SLOT_LR_HAND) { - setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); + if ((rh != null) && (!rh.isArmor() || (rh.getArmorItem().getItemType() != ArmorType.SIGIL))) + { + setPaperdollItem(PAPERDOLL_RHAND, null); + } setPaperdollItem(PAPERDOLL_RHAND, item); } else if (targetSlot == Item.SLOT_L_HAND) { final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); - if (rh != null) + if ((rh != null) && (rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE))) { - if (item.getItemType() == ArmorType.SIGIL) - { - if ((rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) || (rh.getItemType() == WeaponType.POLE) || (rh.getItemType() == WeaponType.DUALFIST) || (rh.getItemType() == WeaponType.DUALBLUNT) || (rh.getItemType() == WeaponType.DUALDAGGER) || (rh.getItemType() == WeaponType.DUAL) || (rh.getItemType() == WeaponType.BLUNT) || (rh.getItemType() == WeaponType.SWORD) || (rh.getItemType() == WeaponType.CROSSBOW) || (rh.getItemType() == WeaponType.TWOHANDCROSSBOW)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE)))) - { - setPaperdollItem(PAPERDOLL_RHAND, null); - } - } - else if ((rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) && (item.getItemType() == EtcItemType.ARROW)) || (((rh.getItemType() == WeaponType.CROSSBOW) || (rh.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (item.getItemType() == EtcItemType.BOLT)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE)))) + if (!item.isArmor() || (item.getArmorItem().getItemType() != ArmorType.SIGIL)) { setPaperdollItem(PAPERDOLL_RHAND, null); } @@ -2096,6 +2068,18 @@ public abstract class Inventory extends ItemContainer return _totalWeight; } + /** + * Reduce the arrow number of the Creature.
+ *
+ * Overridden in: + *
  • PlayerInstance

  • + * @param type + */ + public void reduceAmmunitionCount(EtcItemType type) + { + // Default is to do nothing. + } + /** * Return the ItemInstance of the arrows needed for this bow. * @param bow : Item designating the bow @@ -2462,18 +2446,6 @@ public abstract class Inventory extends ItemContainer _blockedItemSlotsMask = itemSlotsMask; } - /** - * Reduce the arrow number of the Creature.
    - *
    - * Overridden in: - *
  • PlayerInstance

  • - * @param type - */ - public void reduceArrowCount(EtcItemType type) - { - // default is to do nothing - } - /** * Gets the items in paperdoll slots filtered by filter. * @param filters multiple filters diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java index acb8e928ca..c33ff6bc14 100644 --- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java @@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDe import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDrop; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer; import org.l2jmobius.gameserver.model.items.Item; +import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.variables.ItemVariables; @@ -955,26 +956,52 @@ public class PlayerInventory extends Inventory * @param type */ @Override - public void reduceArrowCount(EtcItemType type) + public void reduceAmmunitionCount(EtcItemType type) { if ((type != EtcItemType.ARROW) && (type != EtcItemType.BOLT)) { - LOGGER.log(Level.WARNING, type.toString(), " which is not arrow type passed to PlayerInstance.reduceArrowCount()"); + LOGGER.log(Level.WARNING, type.toString(), " which is not ammo type."); return; } - final ItemInstance arrows = getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if ((arrows == null) || (arrows.getItemType() != type)) + final Weapon weapon = _owner.getActiveWeaponItem(); + if (weapon == null) { return; } - if (arrows.getEtcItem().isInfinite()) // Null-safe due to type checks above + ItemInstance ammunition = null; + switch (weapon.getItemType()) + { + case BOW: + { + ammunition = findArrowForBow(weapon); + break; + } + case CROSSBOW: + case TWOHANDCROSSBOW: + { + ammunition = findBoltForCrossBow(weapon); + break; + } + default: + { + return; + } + } + + if ((ammunition == null) || (ammunition.getItemType() != type)) { return; } - updateItemCountNoDbUpdate(null, arrows, -1, _owner, null); + if (ammunition.getEtcItem().isInfinite()) + { + return; + } + + // Reduce item count. + updateItemCountNoDbUpdate(null, ammunition, -1, _owner, null); } /** diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java new file mode 100644 index 0000000000..101e948523 --- /dev/null +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java @@ -0,0 +1,44 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.model.skills; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; + +/** + * @author Mobius + */ +public class AmmunitionSkillList +{ + private static final Set SKILLS = ConcurrentHashMap.newKeySet(); + + public static void add(List skills) + { + for (ItemSkillHolder skill : skills) + { + SKILLS.add(skill.getSkillId()); + } + } + + public static Set values() + { + return SKILLS; + } +} diff --git a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 6437b28779..d53854ae40 100644 --- a/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_8.0_Homunculus/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -53,8 +53,10 @@ import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder; import org.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; import org.l2jmobius.gameserver.model.instancezone.Instance; +import org.l2jmobius.gameserver.model.itemcontainer.Inventory; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.quest.Quest; import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.siege.Fort; @@ -668,6 +670,13 @@ public class EnterWorld implements IClientIncomingPacket player.getInventory().equipItemAndRecord(agathion); } + // Old ammunition check. + final ItemInstance leftHandItem = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); + if ((leftHandItem != null) && ((leftHandItem.getItemType() == EtcItemType.ARROW) || (leftHandItem.getItemType() == EtcItemType.BOLT))) + { + player.getInventory().unEquipItemInBodySlot(Inventory.PAPERDOLL_LHAND); + } + if (Config.ENABLE_ATTENDANCE_REWARDS) { ThreadPool.schedule(() -> diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/00000-00099.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/00000-00099.xml index e6fba3adec..756f232d08 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/00000-00099.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/00000-00099.xml @@ -398,9 +398,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/01300-01399.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/01300-01399.xml index 938dca7dd1..9c7c67be3b 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/01300-01399.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/01300-01399.xml @@ -749,9 +749,8 @@ - + - @@ -764,9 +763,8 @@ - + - @@ -779,9 +777,8 @@ - + - @@ -794,9 +791,8 @@ - + - @@ -809,9 +805,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/09600-09699.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/09600-09699.xml index 5023069c35..05fea0f14b 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/09600-09699.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/09600-09699.xml @@ -461,9 +461,8 @@ - + - @@ -474,9 +473,8 @@ - + - @@ -488,9 +486,8 @@ - + - @@ -502,9 +499,8 @@ - + - @@ -516,9 +512,8 @@ - + - @@ -530,9 +525,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/18500-18599.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/18500-18599.xml index e518e0686b..6d4f073c28 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/18500-18599.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/18500-18599.xml @@ -879,9 +879,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/19400-19499.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/19400-19499.xml index 53df60361b..e386d35760 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/19400-19499.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/19400-19499.xml @@ -607,9 +607,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22000-22099.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22000-22099.xml index 01a72a5abd..003b6ad535 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22000-22099.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22000-22099.xml @@ -1338,9 +1338,8 @@ - + - @@ -1355,9 +1354,8 @@ - + - @@ -1372,9 +1370,8 @@ - + - @@ -1389,9 +1386,8 @@ - + - @@ -1406,9 +1402,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22100-22199.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22100-22199.xml index f59c2edc59..d81f8961a6 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22100-22199.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/22100-22199.xml @@ -815,9 +815,8 @@ - + - @@ -832,9 +831,8 @@ - + - @@ -849,9 +847,8 @@ - + - @@ -866,9 +863,8 @@ - + - @@ -883,9 +879,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/30300-30399.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/30300-30399.xml index 0dc60fa9bd..5e1cf9b642 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/30300-30399.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/30300-30399.xml @@ -1328,9 +1328,8 @@ - + - @@ -1338,9 +1337,8 @@ - + - @@ -1348,9 +1346,8 @@ - + - @@ -1358,9 +1355,8 @@ - + - @@ -1368,9 +1364,8 @@ - + - @@ -1378,9 +1373,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/32200-32299.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/32200-32299.xml index 2f3a6b61da..4d379ddebf 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/32200-32299.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/32200-32299.xml @@ -922,9 +922,8 @@ - + - @@ -934,9 +933,8 @@ - + - @@ -947,9 +945,8 @@ - + - @@ -960,9 +957,8 @@ - + - @@ -973,9 +969,8 @@ - + - @@ -986,9 +981,8 @@ - + - @@ -999,9 +993,8 @@ - + - @@ -1012,9 +1005,8 @@ - + - @@ -1024,9 +1016,8 @@ - + - @@ -1037,9 +1028,8 @@ - + - @@ -1050,9 +1040,8 @@ - + - @@ -1063,9 +1052,8 @@ - + - @@ -1076,9 +1064,8 @@ - + - @@ -1089,9 +1076,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45400-45499.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45400-45499.xml index 9d3c537ef1..5a77e0dd97 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45400-45499.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45400-45499.xml @@ -269,7 +269,7 @@ - + @@ -281,7 +281,7 @@ - + diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45500-45599.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45500-45599.xml index f6a477761f..81594e457a 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45500-45599.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/45500-45599.xml @@ -1560,9 +1560,8 @@ - + - @@ -1577,9 +1576,8 @@ - + - @@ -1594,9 +1592,8 @@ - + - @@ -1611,9 +1608,8 @@ - + - @@ -1628,9 +1624,8 @@ - + - @@ -1645,9 +1640,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/80400-80499.xml b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/80400-80499.xml index 8b080cb617..daa4b51247 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/80400-80499.xml +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/dist/game/data/stats/items/80400-80499.xml @@ -450,9 +450,8 @@ - + - @@ -463,9 +462,8 @@ - + - diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/ItemTable.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/ItemTable.java index 0a0be13537..bf30b2162c 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/ItemTable.java +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/data/ItemTable.java @@ -47,11 +47,14 @@ import org.l2jmobius.gameserver.model.actor.instance.EventMonsterInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.events.EventDispatcher; import org.l2jmobius.gameserver.model.events.impl.item.OnItemCreate; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.items.Armor; import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.util.DocumentItem; import org.l2jmobius.gameserver.util.GMAudit; @@ -194,6 +197,15 @@ public class ItemTable if (item instanceof EtcItem) { _etcItems.put(item.getId(), (EtcItem) item); + + if ((item.getItemType() == EtcItemType.ARROW) || (item.getItemType() == EtcItemType.BOLT)) + { + final List skills = item.getAllSkills(); + if (skills != null) + { + AmmunitionSkillList.add(skills); + } + } } else if (item instanceof Armor) { diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Creature.java index 4ecb85e742..0128305549 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -1154,11 +1154,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe // Try to do what is expected by having more attack speed. // final int reuse = (int) (Formulas.calculateReuseTime(this, weaponItem) / (Math.max(1, _stat.getAttackSpeedMultiplier() - 1))); - // Consume arrows + // Consume ammunition. final Inventory inventory = getInventory(); if (inventory != null) { - inventory.reduceArrowCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); + inventory.reduceAmmunitionCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); } // Check if the Creature is a PlayerInstance diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index 8cc0df94e9..0621c22c34 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -220,6 +220,7 @@ import org.l2jmobius.gameserver.model.holders.AutoPlaySettingsHolder; import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder; import org.l2jmobius.gameserver.model.holders.DamageTakenHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.MovieHolder; import org.l2jmobius.gameserver.model.holders.PlayerEventHolder; import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder; @@ -261,6 +262,7 @@ import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Siege; import org.l2jmobius.gameserver.model.skills.AbnormalType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.model.skills.BuffInfo; import org.l2jmobius.gameserver.model.skills.CommonSkill; import org.l2jmobius.gameserver.model.skills.Skill; @@ -725,6 +727,8 @@ public class PlayerInstance extends Playable private BroochJewel _activeRubyJewel = null; private BroochJewel _activeShappireJewel = null; + private int _lastAmmunitionId = 0; + /** Event parameters */ private PlayerEventHolder eventStatus = null; @@ -853,7 +857,7 @@ public class PlayerInstance extends Playable // Shared dualclass skills. private static final String KNOWN_DUAL_SKILLS_VAR = "KNOWN_DUAL_SKILLS"; - private static final int[] DUAL_CLASS_SKILLS = new int[] + private static final int[] DUAL_CLASS_SKILLS = { 19222, // Dignity of the Exalted 19223, // Belief of the Exalted @@ -4439,20 +4443,6 @@ public class PlayerInstance extends Playable else { addItem("Pickup", target, null, true); - // Auto-Equip arrows/bolts if player has a bow/crossbow and player picks up arrows/bolts. - final ItemInstance weapon = _inventory.getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItem etcItem = target.getEtcItem(); - if (etcItem != null) - { - final EtcItemType itemType = etcItem.getItemType(); - if (((weapon.getItemType() == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) || (((weapon.getItemType() == WeaponType.CROSSBOW) || (weapon.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) - { - checkAndEquipAmmunition(itemType); - } - } - } } } } @@ -5772,33 +5762,85 @@ public class PlayerInstance extends Playable @Override protected boolean checkAndEquipAmmunition(EtcItemType type) { - ItemInstance arrows = _inventory.getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if (arrows == null) + ItemInstance ammunition = null; + final Weapon weapon = getActiveWeaponItem(); + if (type == EtcItemType.ARROW) { - final Weapon weapon = getActiveWeaponItem(); - if (type == EtcItemType.ARROW) - { - arrows = _inventory.findArrowForBow(weapon); - } - else if (type == EtcItemType.BOLT) - { - arrows = _inventory.findBoltForCrossBow(weapon); - } - if (arrows != null) - { - // Equip arrows needed in left hand - _inventory.setPaperdollItem(Inventory.PAPERDOLL_LHAND, arrows); - sendItemList(); - return true; - } + ammunition = _inventory.findArrowForBow(weapon); } - else + else if (type == EtcItemType.BOLT) { + ammunition = _inventory.findBoltForCrossBow(weapon); + } + + if (ammunition != null) + { + addAmmunitionSkills(ammunition); + sendItemList(); return true; } + + removeAmmunitionSkills(); return false; } + private void addAmmunitionSkills(ItemInstance ammunition) + { + final int currentAmmunitionId = ammunition.getId(); + if (_lastAmmunitionId == currentAmmunitionId) + { + return; + } + removeAmmunitionSkills(); + _lastAmmunitionId = currentAmmunitionId; + + final List skills = ammunition.getItem().getAllSkills(); + if (skills == null) + { + return; + } + + boolean sendSkillList = false; + for (ItemSkillHolder holder : skills) + { + if (!isAffectedBySkill(holder)) + { + final Skill skill = holder.getSkill(); + if (skill.isPassive()) + { + addSkill(skill); + sendSkillList = true; + } + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + + public void removeAmmunitionSkills() + { + if (_lastAmmunitionId == 0) + { + return; + } + _lastAmmunitionId = 0; + + boolean sendSkillList = false; + for (Integer skillId : AmmunitionSkillList.values()) + { + if (removeSkill(skillId.intValue(), true) != null) + { + sendSkillList = true; + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + /** * Disarm the player's weapon. * @return {@code true} if the player was disarmed or doesn't have a weapon to disarm, {@code false} otherwise. diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java index 157c2d27ba..93a9cf3335 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java @@ -53,14 +53,12 @@ import org.l2jmobius.gameserver.model.holders.AgathionSkillHolder; import org.l2jmobius.gameserver.model.holders.ArmorsetSkillHolder; import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder; -import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.appearance.AppearanceStone; import org.l2jmobius.gameserver.model.items.appearance.AppearanceType; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; import org.l2jmobius.gameserver.model.items.type.ArmorType; import org.l2jmobius.gameserver.model.items.type.EtcItemType; -import org.l2jmobius.gameserver.model.items.type.ItemType; import org.l2jmobius.gameserver.model.items.type.WeaponType; import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.SkillConditionScope; @@ -231,33 +229,50 @@ public abstract class Inventory extends ItemContainer @Override public void notifyUnequiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) + if ((slot != PAPERDOLL_RHAND) || !item.isWeapon()) { return; } - if (item.getItemType() == WeaponType.BOW) + switch (item.getWeaponItem().getItemType()) { - final ItemInstance arrow = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (arrow != null) + case BOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (bolts != null) + case CROSSBOW: + case TWOHANDCROSSBOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if (item.getItemType() == WeaponType.FISHINGROD) - { - final ItemInstance lure = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (lure != null) + case FISHINGROD: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (leftHandItem != null) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + break; } } } @@ -265,27 +280,6 @@ public abstract class Inventory extends ItemContainer @Override public void notifyEquiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) - { - return; - } - - if (item.getItemType() == WeaponType.BOW) - { - final ItemInstance arrow = inventory.findArrowForBow(item.getItem()); - if (arrow != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, arrow); - } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.findBoltForCrossBow(item.getItem()); - if (bolts != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, bolts); - } - } } } @@ -1847,24 +1841,6 @@ public abstract class Inventory extends ItemContainer return; } - // Equip only identical grade arrows. - final EtcItem etcItem = item.getEtcItem(); - if (etcItem != null) - { - final ItemInstance weapon = getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItemType itemType = etcItem.getItemType(); - final ItemType weaponItemType = weapon.getItemType(); - if ((((weaponItemType == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) // - || (((weaponItemType == WeaponType.CROSSBOW) || (weaponItemType == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) // - && (weapon.getItem().getCrystalTypePlus() != item.getItem().getCrystalTypePlus())) - { - return; - } - } - } - final PlayerInstance player = (PlayerInstance) getOwner(); if (!player.canOverrideCond(PlayerCondOverride.ITEM_CONDITIONS) && !player.isHero() && item.isHeroItem()) { @@ -1885,27 +1861,23 @@ public abstract class Inventory extends ItemContainer } } - // don't care about arrows, listener will unequip them (hopefully) // handle full armor // formal dress if (targetSlot == Item.SLOT_LR_HAND) { - setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); + if ((rh != null) && (!rh.isArmor() || (rh.getArmorItem().getItemType() != ArmorType.SIGIL))) + { + setPaperdollItem(PAPERDOLL_RHAND, null); + } setPaperdollItem(PAPERDOLL_RHAND, item); } else if (targetSlot == Item.SLOT_L_HAND) { final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); - if (rh != null) + if ((rh != null) && (rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE))) { - if (item.getItemType() == ArmorType.SIGIL) - { - if ((rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) || (rh.getItemType() == WeaponType.POLE) || (rh.getItemType() == WeaponType.DUALFIST) || (rh.getItemType() == WeaponType.DUALBLUNT) || (rh.getItemType() == WeaponType.DUALDAGGER) || (rh.getItemType() == WeaponType.DUAL) || (rh.getItemType() == WeaponType.BLUNT) || (rh.getItemType() == WeaponType.SWORD) || (rh.getItemType() == WeaponType.CROSSBOW) || (rh.getItemType() == WeaponType.TWOHANDCROSSBOW)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE)))) - { - setPaperdollItem(PAPERDOLL_RHAND, null); - } - } - else if ((rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) && (item.getItemType() == EtcItemType.ARROW)) || (((rh.getItemType() == WeaponType.CROSSBOW) || (rh.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (item.getItemType() == EtcItemType.BOLT)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE)))) + if (!item.isArmor() || (item.getArmorItem().getItemType() != ArmorType.SIGIL)) { setPaperdollItem(PAPERDOLL_RHAND, null); } @@ -2096,6 +2068,18 @@ public abstract class Inventory extends ItemContainer return _totalWeight; } + /** + * Reduce the arrow number of the Creature.
    + *
    + * Overridden in: + *
  • PlayerInstance

  • + * @param type + */ + public void reduceAmmunitionCount(EtcItemType type) + { + // Default is to do nothing. + } + /** * Return the ItemInstance of the arrows needed for this bow. * @param bow : Item designating the bow @@ -2462,18 +2446,6 @@ public abstract class Inventory extends ItemContainer _blockedItemSlotsMask = itemSlotsMask; } - /** - * Reduce the arrow number of the Creature.
    - *
    - * Overridden in: - *
  • PlayerInstance

  • - * @param type - */ - public void reduceArrowCount(EtcItemType type) - { - // default is to do nothing - } - /** * Gets the items in paperdoll slots filtered by filter. * @param filters multiple filters diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java index acb8e928ca..c33ff6bc14 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java @@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDe import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDrop; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer; import org.l2jmobius.gameserver.model.items.Item; +import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.variables.ItemVariables; @@ -955,26 +956,52 @@ public class PlayerInventory extends Inventory * @param type */ @Override - public void reduceArrowCount(EtcItemType type) + public void reduceAmmunitionCount(EtcItemType type) { if ((type != EtcItemType.ARROW) && (type != EtcItemType.BOLT)) { - LOGGER.log(Level.WARNING, type.toString(), " which is not arrow type passed to PlayerInstance.reduceArrowCount()"); + LOGGER.log(Level.WARNING, type.toString(), " which is not ammo type."); return; } - final ItemInstance arrows = getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if ((arrows == null) || (arrows.getItemType() != type)) + final Weapon weapon = _owner.getActiveWeaponItem(); + if (weapon == null) { return; } - if (arrows.getEtcItem().isInfinite()) // Null-safe due to type checks above + ItemInstance ammunition = null; + switch (weapon.getItemType()) + { + case BOW: + { + ammunition = findArrowForBow(weapon); + break; + } + case CROSSBOW: + case TWOHANDCROSSBOW: + { + ammunition = findBoltForCrossBow(weapon); + break; + } + default: + { + return; + } + } + + if ((ammunition == null) || (ammunition.getItemType() != type)) { return; } - updateItemCountNoDbUpdate(null, arrows, -1, _owner, null); + if (ammunition.getEtcItem().isInfinite()) + { + return; + } + + // Reduce item count. + updateItemCountNoDbUpdate(null, ammunition, -1, _owner, null); } /** diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java new file mode 100644 index 0000000000..101e948523 --- /dev/null +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java @@ -0,0 +1,44 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.model.skills; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; + +/** + * @author Mobius + */ +public class AmmunitionSkillList +{ + private static final Set SKILLS = ConcurrentHashMap.newKeySet(); + + public static void add(List skills) + { + for (ItemSkillHolder skill : skills) + { + SKILLS.add(skill.getSkillId()); + } + } + + public static Set values() + { + return SKILLS; + } +} diff --git a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 6437b28779..d53854ae40 100644 --- a/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_9.0_ReturnOfTheQueenAnt/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -53,8 +53,10 @@ import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder; import org.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; import org.l2jmobius.gameserver.model.instancezone.Instance; +import org.l2jmobius.gameserver.model.itemcontainer.Inventory; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.quest.Quest; import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.siege.Fort; @@ -668,6 +670,13 @@ public class EnterWorld implements IClientIncomingPacket player.getInventory().equipItemAndRecord(agathion); } + // Old ammunition check. + final ItemInstance leftHandItem = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); + if ((leftHandItem != null) && ((leftHandItem.getItemType() == EtcItemType.ARROW) || (leftHandItem.getItemType() == EtcItemType.BOLT))) + { + player.getInventory().unEquipItemInBodySlot(Inventory.PAPERDOLL_LHAND); + } + if (Config.ENABLE_ATTENDANCE_REWARDS) { ThreadPool.schedule(() -> diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/00000-00099.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/00000-00099.xml index 377ebbb28e..34d39ccbc5 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/00000-00099.xml +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/00000-00099.xml @@ -403,9 +403,8 @@ - + - diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/01300-01399.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/01300-01399.xml index 5d0edc4694..0228b4a1c7 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/01300-01399.xml +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/01300-01399.xml @@ -749,9 +749,8 @@ - + - @@ -764,9 +763,8 @@ - + - @@ -779,9 +777,8 @@ - + - @@ -794,9 +791,8 @@ - + - @@ -809,9 +805,8 @@ - + - diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/09600-09699.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/09600-09699.xml index df0e0ed4cd..b97642ca6b 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/09600-09699.xml +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/09600-09699.xml @@ -3,9 +3,8 @@ - + - diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/32200-32299.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/32200-32299.xml index 46c408e0b5..a41ea2bdec 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/32200-32299.xml +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/32200-32299.xml @@ -3,9 +3,8 @@ - + - @@ -15,9 +14,8 @@ - + - @@ -28,9 +26,8 @@ - + - @@ -41,9 +38,8 @@ - + - @@ -54,9 +50,8 @@ - + - @@ -67,9 +62,8 @@ - + - @@ -79,9 +73,8 @@ - + - @@ -92,9 +85,8 @@ - + - @@ -104,9 +96,8 @@ - + - @@ -117,9 +108,8 @@ - + - @@ -130,9 +120,8 @@ - + - @@ -143,9 +132,8 @@ - + - diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/ItemTable.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/ItemTable.java index 0a0be13537..bf30b2162c 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/ItemTable.java +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/ItemTable.java @@ -47,11 +47,14 @@ import org.l2jmobius.gameserver.model.actor.instance.EventMonsterInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.events.EventDispatcher; import org.l2jmobius.gameserver.model.events.impl.item.OnItemCreate; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.items.Armor; import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.util.DocumentItem; import org.l2jmobius.gameserver.util.GMAudit; @@ -194,6 +197,15 @@ public class ItemTable if (item instanceof EtcItem) { _etcItems.put(item.getId(), (EtcItem) item); + + if ((item.getItemType() == EtcItemType.ARROW) || (item.getItemType() == EtcItemType.BOLT)) + { + final List skills = item.getAllSkills(); + if (skills != null) + { + AmmunitionSkillList.add(skills); + } + } } else if (item instanceof Armor) { diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Creature.java index ccc4dc40ac..a8e58ec1e7 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -1158,11 +1158,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe // Try to do what is expected by having more attack speed. // final int reuse = (int) (Formulas.calculateReuseTime(this, weaponItem) / (Math.max(1, _stat.getAttackSpeedMultiplier() - 1))); - // Consume arrows + // Consume ammunition. final Inventory inventory = getInventory(); if (inventory != null) { - inventory.reduceArrowCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); + inventory.reduceAmmunitionCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); } // Check if the Creature is a PlayerInstance diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index 2a3e55df8b..153017ab56 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -225,6 +225,7 @@ import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder; import org.l2jmobius.gameserver.model.holders.DamageTakenHolder; import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.MovieHolder; import org.l2jmobius.gameserver.model.holders.PlayerEventHolder; import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder; @@ -266,6 +267,7 @@ import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Siege; import org.l2jmobius.gameserver.model.skills.AbnormalType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.model.skills.BuffInfo; import org.l2jmobius.gameserver.model.skills.CommonSkill; import org.l2jmobius.gameserver.model.skills.Skill; @@ -744,6 +746,8 @@ public class PlayerInstance extends Playable private BroochJewel _activeRubyJewel = null; private BroochJewel _activeShappireJewel = null; + private int _lastAmmunitionId = 0; + /** Event parameters */ private PlayerEventHolder eventStatus = null; @@ -4461,20 +4465,6 @@ public class PlayerInstance extends Playable else { addItem("Pickup", target, null, true); - // Auto-Equip arrows/bolts if player has a bow/crossbow and player picks up arrows/bolts. - final ItemInstance weapon = _inventory.getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItem etcItem = target.getEtcItem(); - if (etcItem != null) - { - final EtcItemType itemType = etcItem.getItemType(); - if (((weapon.getItemType() == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) || (((weapon.getItemType() == WeaponType.CROSSBOW) || (weapon.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) - { - checkAndEquipAmmunition(itemType); - } - } - } } } } @@ -5772,33 +5762,85 @@ public class PlayerInstance extends Playable @Override protected boolean checkAndEquipAmmunition(EtcItemType type) { - ItemInstance arrows = _inventory.getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if (arrows == null) + ItemInstance ammunition = null; + final Weapon weapon = getActiveWeaponItem(); + if (type == EtcItemType.ARROW) { - final Weapon weapon = getActiveWeaponItem(); - if (type == EtcItemType.ARROW) - { - arrows = _inventory.findArrowForBow(weapon); - } - else if (type == EtcItemType.BOLT) - { - arrows = _inventory.findBoltForCrossBow(weapon); - } - if (arrows != null) - { - // Equip arrows needed in left hand - _inventory.setPaperdollItem(Inventory.PAPERDOLL_LHAND, arrows); - sendItemList(); - return true; - } + ammunition = _inventory.findArrowForBow(weapon); } - else + else if (type == EtcItemType.BOLT) { + ammunition = _inventory.findBoltForCrossBow(weapon); + } + + if (ammunition != null) + { + addAmmunitionSkills(ammunition); + sendItemList(); return true; } + + removeAmmunitionSkills(); return false; } + private void addAmmunitionSkills(ItemInstance ammunition) + { + final int currentAmmunitionId = ammunition.getId(); + if (_lastAmmunitionId == currentAmmunitionId) + { + return; + } + removeAmmunitionSkills(); + _lastAmmunitionId = currentAmmunitionId; + + final List skills = ammunition.getItem().getAllSkills(); + if (skills == null) + { + return; + } + + boolean sendSkillList = false; + for (ItemSkillHolder holder : skills) + { + if (!isAffectedBySkill(holder)) + { + final Skill skill = holder.getSkill(); + if (skill.isPassive()) + { + addSkill(skill); + sendSkillList = true; + } + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + + public void removeAmmunitionSkills() + { + if (_lastAmmunitionId == 0) + { + return; + } + _lastAmmunitionId = 0; + + boolean sendSkillList = false; + for (Integer skillId : AmmunitionSkillList.values()) + { + if (removeSkill(skillId.intValue(), true) != null) + { + sendSkillList = true; + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + /** * Disarm the player's weapon. * @return {@code true} if the player was disarmed or doesn't have a weapon to disarm, {@code false} otherwise. diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java index cc36465e75..37d0a15f05 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java @@ -53,13 +53,12 @@ import org.l2jmobius.gameserver.model.holders.AgathionSkillHolder; import org.l2jmobius.gameserver.model.holders.ArmorsetSkillHolder; import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder; -import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.appearance.AppearanceStone; import org.l2jmobius.gameserver.model.items.appearance.AppearanceType; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.ArmorType; import org.l2jmobius.gameserver.model.items.type.EtcItemType; -import org.l2jmobius.gameserver.model.items.type.ItemType; import org.l2jmobius.gameserver.model.items.type.WeaponType; import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.SkillConditionScope; @@ -230,33 +229,50 @@ public abstract class Inventory extends ItemContainer @Override public void notifyUnequiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) + if ((slot != PAPERDOLL_RHAND) || !item.isWeapon()) { return; } - if (item.getItemType() == WeaponType.BOW) + switch (item.getWeaponItem().getItemType()) { - final ItemInstance arrow = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (arrow != null) + case BOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (bolts != null) + case CROSSBOW: + case TWOHANDCROSSBOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if (item.getItemType() == WeaponType.FISHINGROD) - { - final ItemInstance lure = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (lure != null) + case FISHINGROD: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (leftHandItem != null) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + break; } } } @@ -264,27 +280,6 @@ public abstract class Inventory extends ItemContainer @Override public void notifyEquiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) - { - return; - } - - if (item.getItemType() == WeaponType.BOW) - { - final ItemInstance arrow = inventory.findArrowForBow(item.getItem()); - if (arrow != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, arrow); - } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.findBoltForCrossBow(item.getItem()); - if (bolts != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, bolts); - } - } } } @@ -1846,24 +1841,6 @@ public abstract class Inventory extends ItemContainer return; } - // Equip only identical grade arrows. - final EtcItem etcItem = item.getEtcItem(); - if (etcItem != null) - { - final ItemInstance weapon = getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItemType itemType = etcItem.getItemType(); - final ItemType weaponItemType = weapon.getItemType(); - if ((((weaponItemType == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) // - || (((weaponItemType == WeaponType.CROSSBOW) || (weaponItemType == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) // - && (weapon.getItem().getCrystalTypePlus() != item.getItem().getCrystalTypePlus())) - { - return; - } - } - } - final PlayerInstance player = (PlayerInstance) getOwner(); if (!player.canOverrideCond(PlayerCondOverride.ITEM_CONDITIONS) && !player.isHero() && item.isHeroItem()) { @@ -1884,20 +1861,26 @@ public abstract class Inventory extends ItemContainer } } - // don't care about arrows, listener will unequip them (hopefully) // handle full armor // formal dress if (targetSlot == Item.SLOT_LR_HAND) { - setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); + if ((rh != null) && (!rh.isArmor() || (rh.getArmorItem().getItemType() != ArmorType.SIGIL))) + { + setPaperdollItem(PAPERDOLL_RHAND, null); + } setPaperdollItem(PAPERDOLL_RHAND, item); } else if (targetSlot == Item.SLOT_L_HAND) { final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); - if ((rh != null) && (rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) && (item.getItemType() == EtcItemType.ARROW)) || (((rh.getItemType() == WeaponType.CROSSBOW) || (rh.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (item.getItemType() == EtcItemType.BOLT)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE)))) + if ((rh != null) && (rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE))) { - setPaperdollItem(PAPERDOLL_RHAND, null); + if (!item.isArmor() || (item.getArmorItem().getItemType() != ArmorType.SIGIL)) + { + setPaperdollItem(PAPERDOLL_RHAND, null); + } } setPaperdollItem(PAPERDOLL_LHAND, item); } @@ -2085,6 +2068,18 @@ public abstract class Inventory extends ItemContainer return _totalWeight; } + /** + * Reduce the arrow number of the Creature.
    + *
    + * Overridden in: + *
  • PlayerInstance

  • + * @param type + */ + public void reduceAmmunitionCount(EtcItemType type) + { + // Default is to do nothing. + } + /** * Return the ItemInstance of the arrows needed for this bow. * @param bow : Item designating the bow @@ -2451,18 +2446,6 @@ public abstract class Inventory extends ItemContainer _blockedItemSlotsMask = itemSlotsMask; } - /** - * Reduce the arrow number of the Creature.
    - *
    - * Overridden in: - *
  • PlayerInstance

  • - * @param type - */ - public void reduceArrowCount(EtcItemType type) - { - // default is to do nothing - } - /** * Gets the items in paperdoll slots filtered by filter. * @param filters multiple filters diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java index 3079d1ec2a..e3eff2ef75 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java @@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDe import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDrop; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer; import org.l2jmobius.gameserver.model.items.Item; +import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.variables.ItemVariables; @@ -962,26 +963,52 @@ public class PlayerInventory extends Inventory * @param type */ @Override - public void reduceArrowCount(EtcItemType type) + public void reduceAmmunitionCount(EtcItemType type) { if ((type != EtcItemType.ARROW) && (type != EtcItemType.BOLT)) { - LOGGER.log(Level.WARNING, type.toString(), " which is not arrow type passed to PlayerInstance.reduceArrowCount()"); + LOGGER.log(Level.WARNING, type.toString(), " which is not ammo type."); return; } - final ItemInstance arrows = getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if ((arrows == null) || (arrows.getItemType() != type)) + final Weapon weapon = _owner.getActiveWeaponItem(); + if (weapon == null) { return; } - if (arrows.getEtcItem().isInfinite()) // Null-safe due to type checks above + ItemInstance ammunition = null; + switch (weapon.getItemType()) + { + case BOW: + { + ammunition = findArrowForBow(weapon); + break; + } + case CROSSBOW: + case TWOHANDCROSSBOW: + { + ammunition = findBoltForCrossBow(weapon); + break; + } + default: + { + return; + } + } + + if ((ammunition == null) || (ammunition.getItemType() != type)) { return; } - updateItemCountNoDbUpdate(null, arrows, -1, _owner, null); + if (ammunition.getEtcItem().isInfinite()) + { + return; + } + + // Reduce item count. + updateItemCountNoDbUpdate(null, ammunition, -1, _owner, null); } /** diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java new file mode 100644 index 0000000000..101e948523 --- /dev/null +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java @@ -0,0 +1,44 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.model.skills; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; + +/** + * @author Mobius + */ +public class AmmunitionSkillList +{ + private static final Set SKILLS = ConcurrentHashMap.newKeySet(); + + public static void add(List skills) + { + for (ItemSkillHolder skill : skills) + { + SKILLS.add(skill.getSkillId()); + } + } + + public static Set values() + { + return SKILLS; + } +} diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 1856b6f743..5d9f7a9134 100644 --- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -52,8 +52,10 @@ import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder; import org.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; import org.l2jmobius.gameserver.model.instancezone.Instance; +import org.l2jmobius.gameserver.model.itemcontainer.Inventory; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.quest.Quest; import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.siege.Fort; @@ -678,6 +680,13 @@ public class EnterWorld implements IClientIncomingPacket player.getInventory().equipItemAndRecord(agathion); } + // Old ammunition check. + final ItemInstance leftHandItem = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); + if ((leftHandItem != null) && ((leftHandItem.getItemType() == EtcItemType.ARROW) || (leftHandItem.getItemType() == EtcItemType.BOLT))) + { + player.getInventory().unEquipItemInBodySlot(Inventory.PAPERDOLL_LHAND); + } + if (Config.ENABLE_ATTENDANCE_REWARDS) { ThreadPool.schedule(() -> diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/00000-00099.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/00000-00099.xml index 377ebbb28e..34d39ccbc5 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/00000-00099.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/00000-00099.xml @@ -403,9 +403,8 @@ - + - diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/01300-01399.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/01300-01399.xml index 5d0edc4694..0228b4a1c7 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/01300-01399.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/01300-01399.xml @@ -749,9 +749,8 @@ - + - @@ -764,9 +763,8 @@ - + - @@ -779,9 +777,8 @@ - + - @@ -794,9 +791,8 @@ - + - @@ -809,9 +805,8 @@ - + - diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/09600-09699.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/09600-09699.xml index df0e0ed4cd..b97642ca6b 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/09600-09699.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/09600-09699.xml @@ -3,9 +3,8 @@ - + - diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/32200-32299.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/32200-32299.xml index 46c408e0b5..a41ea2bdec 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/32200-32299.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/32200-32299.xml @@ -3,9 +3,8 @@ - + - @@ -15,9 +14,8 @@ - + - @@ -28,9 +26,8 @@ - + - @@ -41,9 +38,8 @@ - + - @@ -54,9 +50,8 @@ - + - @@ -67,9 +62,8 @@ - + - @@ -79,9 +73,8 @@ - + - @@ -92,9 +85,8 @@ - + - @@ -104,9 +96,8 @@ - + - @@ -117,9 +108,8 @@ - + - @@ -130,9 +120,8 @@ - + - @@ -143,9 +132,8 @@ - + - diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/94800-94899.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/94800-94899.xml index 25a5b80c5d..69ecd083d8 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/94800-94899.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/94800-94899.xml @@ -874,7 +874,7 @@ - + @@ -1075,7 +1075,7 @@ - + @@ -1094,7 +1094,7 @@ - + @@ -1115,7 +1115,7 @@ - + @@ -1136,7 +1136,7 @@ - + @@ -1157,7 +1157,7 @@ - + @@ -1178,7 +1178,7 @@ - + @@ -1199,7 +1199,7 @@ - + @@ -1220,7 +1220,7 @@ - + @@ -1241,7 +1241,7 @@ - + @@ -1261,7 +1261,7 @@ - + @@ -1282,7 +1282,7 @@ - + @@ -1302,9 +1302,8 @@ - + - @@ -1316,9 +1315,8 @@ - + - @@ -1331,9 +1329,8 @@ - + - @@ -1346,9 +1343,8 @@ - + - @@ -1361,9 +1357,8 @@ - + - @@ -1392,7 +1387,7 @@ - + diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95400-95499.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95400-95499.xml index 8d5858f55b..20154e4ecc 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95400-95499.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95400-95499.xml @@ -182,7 +182,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -256,7 +256,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -302,7 +302,7 @@ - + @@ -326,7 +326,7 @@ - + @@ -350,7 +350,7 @@ - + @@ -374,7 +374,7 @@ - + @@ -398,7 +398,7 @@ - + @@ -422,7 +422,7 @@ - + @@ -446,7 +446,7 @@ - + @@ -468,7 +468,7 @@ - + @@ -761,7 +761,7 @@ - + @@ -1097,7 +1097,7 @@ - + diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95600-95699.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95600-95699.xml index 0a680a2fc4..1daf62166d 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95600-95699.xml +++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/95600-95699.xml @@ -1212,7 +1212,7 @@ - + diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/ItemTable.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/ItemTable.java index 0a0be13537..f16a0ab2df 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/ItemTable.java +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/ItemTable.java @@ -47,11 +47,14 @@ import org.l2jmobius.gameserver.model.actor.instance.EventMonsterInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; import org.l2jmobius.gameserver.model.events.EventDispatcher; import org.l2jmobius.gameserver.model.events.impl.item.OnItemCreate; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.items.Armor; import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.util.DocumentItem; import org.l2jmobius.gameserver.util.GMAudit; @@ -194,6 +197,15 @@ public class ItemTable if (item instanceof EtcItem) { _etcItems.put(item.getId(), (EtcItem) item); + + if ((item.getItemType() == EtcItemType.ARROW) || (item.getItemType() == EtcItemType.BOLT) || (item.getItemType() == EtcItemType.ELEMENTAL_ORB)) + { + final List skills = item.getAllSkills(); + if (skills != null) + { + AmmunitionSkillList.add(skills); + } + } } else if (item instanceof Armor) { diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Creature.java index 2b1d3a6988..52e778e7a9 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -1165,11 +1165,11 @@ public abstract class Creature extends WorldObject implements ISkillsHolder, IDe // Try to do what is expected by having more attack speed. // final int reuse = (int) (Formulas.calculateReuseTime(this, weaponItem) / (Math.max(1, _stat.getAttackSpeedMultiplier() - 1))); - // Consume arrows + // Consume ammunition. final Inventory inventory = getInventory(); if (inventory != null) { - inventory.reduceArrowCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); + inventory.reduceAmmunitionCount(crossbow ? EtcItemType.BOLT : EtcItemType.ARROW); } // Check if the Creature is a PlayerInstance diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index 76a972960c..c867b6f13e 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -225,6 +225,7 @@ import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder; import org.l2jmobius.gameserver.model.holders.DamageTakenHolder; import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder; +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.MovieHolder; import org.l2jmobius.gameserver.model.holders.PlayerEventHolder; import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder; @@ -266,6 +267,7 @@ import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Siege; import org.l2jmobius.gameserver.model.skills.AbnormalType; +import org.l2jmobius.gameserver.model.skills.AmmunitionSkillList; import org.l2jmobius.gameserver.model.skills.BuffInfo; import org.l2jmobius.gameserver.model.skills.CommonSkill; import org.l2jmobius.gameserver.model.skills.Skill; @@ -744,6 +746,8 @@ public class PlayerInstance extends Playable private BroochJewel _activeRubyJewel = null; private BroochJewel _activeShappireJewel = null; + private int _lastAmmunitionId = 0; + /** Event parameters */ private PlayerEventHolder eventStatus = null; @@ -4461,20 +4465,6 @@ public class PlayerInstance extends Playable else { addItem("Pickup", target, null, true); - // Auto-Equip arrows/bolts if player has a bow/crossbow and player picks up arrows/bolts. - final ItemInstance weapon = _inventory.getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItem etcItem = target.getEtcItem(); - if (etcItem != null) - { - final EtcItemType itemType = etcItem.getItemType(); - if (((weapon.getItemType() == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) || (((weapon.getItemType() == WeaponType.CROSSBOW) || (weapon.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) - { - checkAndEquipAmmunition(itemType); - } - } - } } } } @@ -5772,37 +5762,89 @@ public class PlayerInstance extends Playable @Override protected boolean checkAndEquipAmmunition(EtcItemType type) { - ItemInstance arrows = _inventory.getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if (arrows == null) + ItemInstance ammunition = null; + final Weapon weapon = getActiveWeaponItem(); + if (type == EtcItemType.ARROW) { - final Weapon weapon = getActiveWeaponItem(); - if (type == EtcItemType.ARROW) - { - arrows = _inventory.findArrowForBow(weapon); - } - else if (type == EtcItemType.BOLT) - { - arrows = _inventory.findBoltForCrossBow(weapon); - } - else if (type == EtcItemType.ELEMENTAL_ORB) - { - arrows = _inventory.findElementalOrbForPistols(weapon); - } - if (arrows != null) - { - // Equip arrows needed in left hand - _inventory.setPaperdollItem(Inventory.PAPERDOLL_LHAND, arrows); - sendItemList(); - return true; - } + ammunition = _inventory.findArrowForBow(weapon); } - else + else if (type == EtcItemType.BOLT) { + ammunition = _inventory.findBoltForCrossBow(weapon); + } + else if (type == EtcItemType.ELEMENTAL_ORB) + { + ammunition = _inventory.findElementalOrbForPistols(weapon); + } + + if (ammunition != null) + { + addAmmunitionSkills(ammunition); + sendItemList(); return true; } + + removeAmmunitionSkills(); return false; } + private void addAmmunitionSkills(ItemInstance ammunition) + { + final int currentAmmunitionId = ammunition.getId(); + if (_lastAmmunitionId == currentAmmunitionId) + { + return; + } + removeAmmunitionSkills(); + _lastAmmunitionId = currentAmmunitionId; + + final List skills = ammunition.getItem().getAllSkills(); + if (skills == null) + { + return; + } + + boolean sendSkillList = false; + for (ItemSkillHolder holder : skills) + { + if (!isAffectedBySkill(holder)) + { + final Skill skill = holder.getSkill(); + if (skill.isPassive()) + { + addSkill(skill); + sendSkillList = true; + } + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + + public void removeAmmunitionSkills() + { + if (_lastAmmunitionId == 0) + { + return; + } + _lastAmmunitionId = 0; + + boolean sendSkillList = false; + for (Integer skillId : AmmunitionSkillList.values()) + { + if (removeSkill(skillId.intValue(), true) != null) + { + sendSkillList = true; + } + } + if (sendSkillList) + { + sendSkillList(); + } + } + /** * Disarm the player's weapon. * @return {@code true} if the player was disarmed or doesn't have a weapon to disarm, {@code false} otherwise. diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java index ae9b8824b2..c1cd9d976f 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java @@ -53,13 +53,12 @@ import org.l2jmobius.gameserver.model.holders.AgathionSkillHolder; import org.l2jmobius.gameserver.model.holders.ArmorsetSkillHolder; import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; import org.l2jmobius.gameserver.model.holders.SkillHolder; -import org.l2jmobius.gameserver.model.items.EtcItem; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.appearance.AppearanceStone; import org.l2jmobius.gameserver.model.items.appearance.AppearanceType; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.ArmorType; import org.l2jmobius.gameserver.model.items.type.EtcItemType; -import org.l2jmobius.gameserver.model.items.type.ItemType; import org.l2jmobius.gameserver.model.items.type.WeaponType; import org.l2jmobius.gameserver.model.skills.Skill; import org.l2jmobius.gameserver.model.skills.SkillConditionScope; @@ -230,33 +229,59 @@ public abstract class Inventory extends ItemContainer @Override public void notifyUnequiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) + if ((slot != PAPERDOLL_RHAND) || !item.isWeapon()) { return; } - if (item.getItemType() == WeaponType.BOW) + switch (item.getWeaponItem().getItemType()) { - final ItemInstance arrow = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (arrow != null) + case BOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (bolts != null) + case CROSSBOW: + case TWOHANDCROSSBOW: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (((leftHandItem != null) && ((leftHandItem.getItemType()) != ArmorType.SIGIL))) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; } - } - else if (item.getItemType() == WeaponType.FISHINGROD) - { - final ItemInstance lure = inventory.getPaperdollItem(PAPERDOLL_LHAND); - if (lure != null) + case PISTOLS: { - inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + final PlayerInstance owner = inventory.getOwner().getActingPlayer(); + if (owner != null) + { + owner.removeAmmunitionSkills(); + } + break; + } + case FISHINGROD: + { + final ItemInstance leftHandItem = inventory.getPaperdollItem(PAPERDOLL_LHAND); + if (leftHandItem != null) + { + inventory.setPaperdollItem(PAPERDOLL_LHAND, null); + } + break; } } } @@ -264,27 +289,6 @@ public abstract class Inventory extends ItemContainer @Override public void notifyEquiped(int slot, ItemInstance item, Inventory inventory) { - if (slot != PAPERDOLL_RHAND) - { - return; - } - - if (item.getItemType() == WeaponType.BOW) - { - final ItemInstance arrow = inventory.findArrowForBow(item.getItem()); - if (arrow != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, arrow); - } - } - else if ((item.getItemType() == WeaponType.CROSSBOW) || (item.getItemType() == WeaponType.TWOHANDCROSSBOW)) - { - final ItemInstance bolts = inventory.findBoltForCrossBow(item.getItem()); - if (bolts != null) - { - inventory.setPaperdollItem(PAPERDOLL_LHAND, bolts); - } - } } } @@ -1846,24 +1850,6 @@ public abstract class Inventory extends ItemContainer return; } - // Equip only identical grade arrows. - final EtcItem etcItem = item.getEtcItem(); - if (etcItem != null) - { - final ItemInstance weapon = getPaperdollItem(Inventory.PAPERDOLL_RHAND); - if (weapon != null) - { - final EtcItemType itemType = etcItem.getItemType(); - final ItemType weaponItemType = weapon.getItemType(); - if ((((weaponItemType == WeaponType.BOW) && (itemType == EtcItemType.ARROW)) // - || (((weaponItemType == WeaponType.CROSSBOW) || (weaponItemType == WeaponType.TWOHANDCROSSBOW)) && (itemType == EtcItemType.BOLT))) // - && (weapon.getItem().getCrystalTypePlus() != item.getItem().getCrystalTypePlus())) - { - return; - } - } - } - final PlayerInstance player = (PlayerInstance) getOwner(); if (!player.canOverrideCond(PlayerCondOverride.ITEM_CONDITIONS) && !player.isHero() && item.isHeroItem()) { @@ -1884,20 +1870,26 @@ public abstract class Inventory extends ItemContainer } } - // don't care about arrows, listener will unequip them (hopefully) // handle full armor // formal dress if (targetSlot == Item.SLOT_LR_HAND) { - setPaperdollItem(PAPERDOLL_LHAND, null); + final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); + if ((rh != null) && (!rh.isArmor() || (rh.getArmorItem().getItemType() != ArmorType.SIGIL))) + { + setPaperdollItem(PAPERDOLL_RHAND, null); + } setPaperdollItem(PAPERDOLL_RHAND, item); } else if (targetSlot == Item.SLOT_L_HAND) { final ItemInstance rh = getPaperdollItem(PAPERDOLL_RHAND); - if ((rh != null) && (rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !(((rh.getItemType() == WeaponType.BOW) && (item.getItemType() == EtcItemType.ARROW)) || (((rh.getItemType() == WeaponType.CROSSBOW) || (rh.getItemType() == WeaponType.TWOHANDCROSSBOW)) && (item.getItemType() == EtcItemType.BOLT)) || ((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE)))) + if ((rh != null) && (rh.getItem().getBodyPart() == Item.SLOT_LR_HAND) && !((rh.getItemType() == WeaponType.FISHINGROD) && (item.getItemType() == EtcItemType.LURE))) { - setPaperdollItem(PAPERDOLL_RHAND, null); + if (!item.isArmor() || (item.getArmorItem().getItemType() != ArmorType.SIGIL)) + { + setPaperdollItem(PAPERDOLL_RHAND, null); + } } setPaperdollItem(PAPERDOLL_LHAND, item); } @@ -2085,6 +2077,18 @@ public abstract class Inventory extends ItemContainer return _totalWeight; } + /** + * Reduce the arrow number of the Creature.
    + *
    + * Overridden in: + *
  • PlayerInstance

  • + * @param type + */ + public void reduceAmmunitionCount(EtcItemType type) + { + // Default is to do nothing. + } + /** * Return the ItemInstance of the arrows needed for this bow. * @param bow : Item designating the bow @@ -2472,18 +2476,6 @@ public abstract class Inventory extends ItemContainer _blockedItemSlotsMask = itemSlotsMask; } - /** - * Reduce the arrow number of the Creature.
    - *
    - * Overridden in: - *
  • PlayerInstance

  • - * @param type - */ - public void reduceArrowCount(EtcItemType type) - { - // default is to do nothing - } - /** * Gets the items in paperdoll slots filtered by filter. * @param filters multiple filters diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java index 3079d1ec2a..e3eff2ef75 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java @@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDe import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemDrop; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer; import org.l2jmobius.gameserver.model.items.Item; +import org.l2jmobius.gameserver.model.items.Weapon; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.variables.ItemVariables; @@ -962,26 +963,52 @@ public class PlayerInventory extends Inventory * @param type */ @Override - public void reduceArrowCount(EtcItemType type) + public void reduceAmmunitionCount(EtcItemType type) { if ((type != EtcItemType.ARROW) && (type != EtcItemType.BOLT)) { - LOGGER.log(Level.WARNING, type.toString(), " which is not arrow type passed to PlayerInstance.reduceArrowCount()"); + LOGGER.log(Level.WARNING, type.toString(), " which is not ammo type."); return; } - final ItemInstance arrows = getPaperdollItem(Inventory.PAPERDOLL_LHAND); - if ((arrows == null) || (arrows.getItemType() != type)) + final Weapon weapon = _owner.getActiveWeaponItem(); + if (weapon == null) { return; } - if (arrows.getEtcItem().isInfinite()) // Null-safe due to type checks above + ItemInstance ammunition = null; + switch (weapon.getItemType()) + { + case BOW: + { + ammunition = findArrowForBow(weapon); + break; + } + case CROSSBOW: + case TWOHANDCROSSBOW: + { + ammunition = findBoltForCrossBow(weapon); + break; + } + default: + { + return; + } + } + + if ((ammunition == null) || (ammunition.getItemType() != type)) { return; } - updateItemCountNoDbUpdate(null, arrows, -1, _owner, null); + if (ammunition.getEtcItem().isInfinite()) + { + return; + } + + // Reduce item count. + updateItemCountNoDbUpdate(null, ammunition, -1, _owner, null); } /** diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java new file mode 100644 index 0000000000..101e948523 --- /dev/null +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/skills/AmmunitionSkillList.java @@ -0,0 +1,44 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.model.skills; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.l2jmobius.gameserver.model.holders.ItemSkillHolder; + +/** + * @author Mobius + */ +public class AmmunitionSkillList +{ + private static final Set SKILLS = ConcurrentHashMap.newKeySet(); + + public static void add(List skills) + { + for (ItemSkillHolder skill : skills) + { + SKILLS.add(skill.getSkillId()); + } + } + + public static Set values() + { + return SKILLS; + } +} diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 24f2b9f59b..d8ad979a2b 100644 --- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -52,8 +52,10 @@ import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder; import org.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; import org.l2jmobius.gameserver.model.instancezone.Instance; +import org.l2jmobius.gameserver.model.itemcontainer.Inventory; import org.l2jmobius.gameserver.model.items.Item; import org.l2jmobius.gameserver.model.items.instance.ItemInstance; +import org.l2jmobius.gameserver.model.items.type.EtcItemType; import org.l2jmobius.gameserver.model.quest.Quest; import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.siege.Fort; @@ -678,6 +680,13 @@ public class EnterWorld implements IClientIncomingPacket player.getInventory().equipItemAndRecord(agathion); } + // Old ammunition check. + final ItemInstance leftHandItem = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND); + if ((leftHandItem != null) && ((leftHandItem.getItemType() == EtcItemType.ARROW) || (leftHandItem.getItemType() == EtcItemType.BOLT) || (leftHandItem.getItemType() == EtcItemType.ELEMENTAL_ORB))) + { + player.getInventory().unEquipItemInBodySlot(Inventory.PAPERDOLL_LHAND); + } + if (Config.ENABLE_ATTENDANCE_REWARDS) { ThreadPool.schedule(() ->