package javastory.channel.handling; import java.awt.Point; import java.rmi.RemoteException; import java.util.List; import java.util.Map; import javastory.channel.ChannelCharacter; import javastory.channel.ChannelClient; import javastory.channel.ChannelServer; import javastory.channel.Party; import javastory.channel.PartyMember; import javastory.channel.anticheat.CheatingOffense; import javastory.channel.client.ActivePlayerStats; import javastory.channel.client.ISkill; import javastory.channel.client.Mount; import javastory.channel.client.Pet; import javastory.channel.life.LifeFactory; import javastory.channel.life.Monster; import javastory.channel.maps.FieldLimitType; import javastory.channel.maps.GameMap; import javastory.channel.maps.GameMapItem; import javastory.channel.maps.GameMapObject; import javastory.channel.maps.GameMapObjectType; import javastory.channel.maps.SavedLocationType; import javastory.channel.packet.MTSCSPacket; import javastory.channel.packet.PetPacket; import javastory.channel.server.InventoryManipulator; import javastory.channel.server.ShopFactory; import javastory.client.GameCharacterUtil; import javastory.game.Equip; import javastory.game.GameConstants; import javastory.game.IdProbabilityEntry; import javastory.game.Inventory; import javastory.game.InventoryType; import javastory.game.Item; import javastory.game.ItemConsumeType; import javastory.game.ItemFlag; import javastory.game.ScrollResult; import javastory.game.Stat; import javastory.game.StatValue; import javastory.game.data.ItemInfoProvider; import javastory.game.data.RandomRewards; import javastory.game.data.RewardItemInfo; import javastory.game.data.RewardSetInfo; import javastory.game.data.SkillInfoProvider; import javastory.game.quest.QuestInfoProvider; import javastory.game.quest.QuestInfoProvider.QuestInfo; import javastory.io.PacketFormatException; import javastory.io.PacketReader; import javastory.scripting.NpcScriptManager; import javastory.tools.Randomizer; import javastory.tools.packets.ChannelPackets; import com.google.common.collect.Lists; public class InventoryHandler { public static void handleItemMove(final PacketReader reader, final ChannelClient c) throws PacketFormatException { reader.skip(4); final byte typeByte = reader.readByte(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = c.getPlayer().getInventoryByType(type); final byte src = (byte) reader.readShort(); final byte dst = (byte) reader.readShort(); final short quantity = reader.readShort(); if (src < 0 && dst > 0) { InventoryManipulator.unequip(c, src, dst); } else if (dst < 0) { InventoryManipulator.equip(c, src, dst); } else if (dst == 0) { InventoryManipulator.drop(c, inventory, src, quantity); } else { InventoryManipulator.move(c, inventory, src, dst); } } public static void handleItemSort(final PacketReader reader, final ChannelClient c) throws PacketFormatException { reader.skip(4); final byte typeByte = reader.readByte(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = c.getPlayer().getInventoryByType(type); boolean sorted = false; while (!sorted) { final byte freeSlot = (byte) inventory.getNextFreeSlot(); if (freeSlot != -1) { byte itemSlot = -1; for (byte i = (byte) (freeSlot + 1); i <= 100; i++) { if (inventory.getItem(i) != null) { itemSlot = i; break; } } if (itemSlot <= 100 && itemSlot > 0) { InventoryManipulator.move(c, inventory, itemSlot, freeSlot); } else { sorted = true; } } } c.write(ChannelPackets.finishedSort(typeByte)); c.write(ChannelPackets.enableActions()); } public static void ItemSort2(final PacketReader reader, final ChannelClient c) { /* * reader.skip(4); byte mode = reader.readByte(); if (mode < 0 || mode > * 5) { return; } Inventory Inv = * c.getPlayer().getInventory(InventoryType.getByType(mode)); * ArrayList<Item> itemarray = new ArrayList<Item>(); for * (Iterator<Item> it = Inv.iterator(); it.hasNext();) { Item item = * (Item) it.next(); itemarray.add((Item) (item.copy())); } * Collections.sort(itemarray); for (Item item : itemarray) { * MapleInventoryManipulator.removeById(c, * InventoryType.getByType(mode), item.getItemId(), item.getQuantity(), * false, false); } for (Item i : itemarray) { * MapleInventoryManipulator.addFromDrop(c, i, false, false); } * c.write(MaplePacketCreator.finishedSort2(mode)); * c.write(MaplePacketCreator.enableActions()); */ } public static void handleUseRewardItem(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final Inventory useInventory = c.getPlayer().getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse != null && toUse.getQuantity() >= 1 && toUse.getItemId() == itemId) { if (!chr.getEquipInventory().isFull() && !chr.getUseInventory().isFull() && !chr.getSetupInventory().isFull() && !chr.getEtcInventory().isFull()) { final ItemInfoProvider ii = ItemInfoProvider.getInstance(); final RewardSetInfo rewardSet = ii.getRewardSet(itemId); if (rewardSet != null) { for (final RewardItemInfo reward : rewardSet.Rewards) { if (Randomizer.nextInt(rewardSet.TotalProbability) < reward.Probability) { if (GameConstants.getInventoryType(reward.ItemId) == InventoryType.EQUIP) { final Item item = ii.getEquipById(reward.ItemId); if (reward.Period != -1) { item.setExpiration(System.currentTimeMillis() + reward.Period * 60 * 60 * 10L); } InventoryManipulator.addbyItem(c, item); } else { InventoryManipulator.addById(c, reward.ItemId, reward.Quantity); } InventoryManipulator.removeById(c, useInventory, itemId, 1, false, false); c.write(ChannelPackets.showRewardItemAnimation(reward.ItemId, reward.Effect)); chr.getMap().broadcastMessage(chr, ChannelPackets.showRewardItemAnimation(reward.ItemId, reward.Effect, chr.getId()), false); break; } } } } else { chr.sendNotice(6, "Insufficient inventory slot."); } } c.write(ChannelPackets.enableActions()); } public static void handleUseItem(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { if (!chr.isAlive()) { c.write(ChannelPackets.enableActions()); return; } reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse == null || toUse.getQuantity() < 1 || toUse.getItemId() != itemId) { c.write(ChannelPackets.enableActions()); return; } if (!FieldLimitType.PotionUse.check(chr.getMap().getFieldLimit())) { if (ItemInfoProvider.getInstance().getItemEffect(toUse.getItemId()).applyTo(chr)) { InventoryManipulator.removeFromSlot(c, useInventory, slot, (short) 1, false); } } else { c.write(ChannelPackets.enableActions()); } } public static void handleUseReturnScroll(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { if (!chr.isAlive()) { c.write(ChannelPackets.enableActions()); return; } reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse == null || toUse.getQuantity() < 1 || toUse.getItemId() != itemId) { c.write(ChannelPackets.enableActions()); return; } if (!FieldLimitType.PotionUse.check(chr.getMap().getFieldLimit())) { if (ItemInfoProvider.getInstance().getItemEffect(toUse.getItemId()).applyReturnScroll(chr)) { InventoryManipulator.removeFromSlot(c, useInventory, slot, (short) 1, false); } else { c.write(ChannelPackets.enableActions()); } } else { c.write(ChannelPackets.enableActions()); } } public static void handleUseUpgradeScroll(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { // Lunar Gloves unlimited scroll reader.skip(4); final byte slot = (byte) reader.readShort(); final byte dst = (byte) reader.readShort(); final byte ws = (byte) reader.readShort(); boolean whiteScroll = false; // white scroll being used? boolean legendarySpirit = false; // legendary spirit skill final ItemInfoProvider ii = ItemInfoProvider.getInstance(); if ((ws & 2) == 2) { whiteScroll = true; } Equip toScroll; final Inventory equippedInventory = chr.getEquippedItemsInventory(); final Inventory equipInventory = chr.getEquipInventory(); if (dst < 0) { toScroll = (Equip) equippedInventory.getItem(dst); } else { // legendary spirit legendarySpirit = true; toScroll = (Equip) equipInventory.getItem(dst); } final byte oldLevel = toScroll.getLevel(); final byte oldFlag = toScroll.getFlag(); if (!GameConstants.isSpecialScroll(toScroll.getItemId()) && !GameConstants.isCleanSlate(toScroll.getItemId())) { if (toScroll.getUpgradeSlots() < 1) { c.write(ChannelPackets.getInventoryFull()); return; } } final Inventory useInventory = chr.getUseInventory(); final Item scroll = useInventory.getItem(slot); Item wscroll = null; // Anti cheat and validation final List<Integer> scrollReqs = ii.getScrollReqs(scroll.getItemId()); if (scrollReqs.size() > 0 && !scrollReqs.contains(toScroll.getItemId())) { c.write(ChannelPackets.getInventoryFull()); return; } if (whiteScroll) { wscroll = useInventory.findById(2340000); if (wscroll == null || wscroll.getItemId() != 2340000) { whiteScroll = false; } } if (!GameConstants.isChaosScroll(scroll.getItemId()) && !GameConstants.isCleanSlate(scroll.getItemId())) { if (!ii.canScroll(scroll.getItemId(), toScroll.getItemId())) { return; } } if (scroll.getQuantity() <= 0) { return; } if (legendarySpirit) { if (chr.getCurrentSkillLevel(SkillInfoProvider.getSkill(1003)) <= 0) { // AutobanManager.getInstance().addPoints(c, 50, 120000, // "Using the Skill 'Legendary Spirit' without having it."); return; } } // Scroll Success/ Failure/ Curse final Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll); ScrollResult scrollSuccess; if (scrolled == null) { scrollSuccess = ScrollResult.CURSE; } else if (scrolled.getLevel() > oldLevel) { scrollSuccess = ScrollResult.SUCCESS; } else if (GameConstants.isCleanSlate(scroll.getItemId()) && scrolled.getLevel() == oldLevel + 1) { scrollSuccess = ScrollResult.SUCCESS; } else if (GameConstants.isSpecialScroll(scroll.getItemId()) && scrolled.getFlag() > oldFlag) { scrollSuccess = ScrollResult.SUCCESS; } else { scrollSuccess = ScrollResult.FAIL; } // Update useInventory.removeItem(scroll.getPosition(), (short) 1, false); if (whiteScroll) { InventoryManipulator.removeFromSlot(c, useInventory, wscroll.getPosition(), (short) 1, false, false); } if (scrollSuccess == ScrollResult.CURSE) { c.write(ChannelPackets.scrolledItem(scroll, toScroll, true)); if (dst < 0) { equippedInventory.removeItem(toScroll.getPosition()); } else { equipInventory.removeItem(toScroll.getPosition()); } } else { c.write(ChannelPackets.scrolledItem(scroll, scrolled, false)); } chr.getMap().broadcastMessage(ChannelPackets.getScrollEffect(c.getPlayer().getId(), scrollSuccess, legendarySpirit)); // equipped item was scrolled and changed if (dst < 0 && (scrollSuccess == ScrollResult.SUCCESS || scrollSuccess == ScrollResult.CURSE)) { chr.equipChanged(); } } public static void handleUseSkillBook(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse == null || toUse.getQuantity() < 1 || toUse.getItemId() != itemId) { return; } final Map<String, Integer> skilldata = ItemInfoProvider.getInstance().getSkillStats(toUse.getItemId()); if (skilldata == null) { // Hacking or used an unknown item return; } boolean canuse = false, success = false; final int skill = 0, maxlevel = 0; final int SuccessRate = skilldata.get("success"); final int ReqSkillLevel = skilldata.get("reqSkillLevel"); final int MasterLevel = skilldata.get("masterLevel"); byte i = 0; Integer CurrentLoopedSkillId; for (;;) { CurrentLoopedSkillId = skilldata.get("skillid" + i); i++; if (CurrentLoopedSkillId == null) { break; // End of data } if (CurrentLoopedSkillId / 100000 == chr.getJobId() / 10) { final ISkill CurrSkillData = SkillInfoProvider.getSkill(CurrentLoopedSkillId); if (chr.getCurrentSkillLevel(CurrSkillData) >= ReqSkillLevel && chr.getMasterSkillLevel(CurrSkillData) < MasterLevel) { canuse = true; if (Randomizer.nextInt(99) <= SuccessRate && SuccessRate != 0) { success = true; final ISkill skill2 = CurrSkillData; chr.changeSkillLevel(skill2, chr.getCurrentSkillLevel(skill2), (byte) MasterLevel); } else { success = false; } InventoryManipulator.removeFromSlot(c, useInventory, slot, (short) 1, false); break; } else { // Failed to meet skill requirements canuse = false; } } } c.write(ChannelPackets.useSkillBook(chr, skill, maxlevel, canuse, success)); } public static void handleUseCatchItem(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemid = reader.readInt(); final Monster mob = chr.getMap().getMonsterByOid(reader.readInt()); final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse != null && toUse.getQuantity() > 0 && toUse.getItemId() == itemid && mob != null) { switch (itemid) { case 2270002: { // Characteristic Stone final GameMap map = chr.getMap(); if (mob.getHp() <= mob.getMobMaxHp() / 2) { map.broadcastMessage(ChannelPackets.catchMonster(mob.getId(), itemid, (byte) 1)); map.killMonster(mob, chr, true, false, (byte) 0); InventoryManipulator.removeById(c, useInventory, itemid, 1, false, false); } else { map.broadcastMessage(ChannelPackets.catchMonster(mob.getId(), itemid, (byte) 0)); chr.sendNotice(5, "The monster has too much physical strength, so you cannot catch it."); } break; } case 2270000: { // Pheromone Perfume if (mob.getId() != 9300101) { break; } final GameMap map = c.getPlayer().getMap(); map.broadcastMessage(ChannelPackets.catchMonster(mob.getId(), itemid, (byte) 1)); map.killMonster(mob, chr, true, false, (byte) 0); InventoryManipulator.addById(c, 1902000, (short) 1, null); InventoryManipulator.removeById(c, useInventory, itemid, 1, false, false); break; } case 2270003: { // Cliff's Magic Cane if (mob.getId() != 9500320) { break; } final GameMap map = c.getPlayer().getMap(); if (mob.getHp() <= mob.getMobMaxHp() / 2) { map.broadcastMessage(ChannelPackets.catchMonster(mob.getId(), itemid, (byte) 1)); map.killMonster(mob, chr, true, false, (byte) 0); InventoryManipulator.removeById(c, useInventory, itemid, 1, false, false); } else { map.broadcastMessage(ChannelPackets.catchMonster(mob.getId(), itemid, (byte) 0)); chr.sendNotice(5, "The monster has too much physical strength, so you cannot catch it."); } break; } } } c.write(ChannelPackets.enableActions()); // c.getPlayer().setAPQScore(c.getPlayer().getAPQScore() + 1); // c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.updateAriantPQRanking(c.getPlayer().getName(), // c.getPlayer().getAPQScore(), false)); } public static void handleUseMountFood(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemid = reader.readInt(); // 2260000 usually final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); final Mount mount = chr.getMount(); if (toUse != null && toUse.getQuantity() > 0 && toUse.getItemId() == itemid && mount != null) { final int fatigue = mount.getFatigue(); boolean levelup = false; mount.setFatigue(-30); if (fatigue > 0) { mount.increaseExp(); final int level = mount.getLevel(); if (mount.getExp() >= GameConstants.getMountExpNeededForLevel(level + 1) && level < 31) { mount.setLevel(level + 1); levelup = true; } } chr.getMap().broadcastMessage(ChannelPackets.updateMount(chr, levelup)); InventoryManipulator.removeFromSlot(c, useInventory, slot, (short) 1, false); } c.write(ChannelPackets.enableActions()); } public static void handleUseScriptedNpcItem(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse != null && toUse.getQuantity() >= 1 && toUse.getItemId() == itemId) { switch (toUse.getItemId()) { case 2430007: { // Blank Compass final Inventory setupInventory = chr.getSetupInventory(); InventoryManipulator.removeFromSlot(c, useInventory, slot, (byte) 1, false); if (setupInventory.countById(3994102) >= 20 // Compass Letter // "North" && setupInventory.countById(3994103) >= 20 // Compass // Letter // "South" && setupInventory.countById(3994104) >= 20 // Compass // Letter // "East" && setupInventory.countById(3994105) >= 20) { // Compass // Letter // "West" InventoryManipulator.addById(c, 2430008, (short) 1); // Gold // Compass InventoryManipulator.removeById(c, setupInventory, 3994102, 20, false, false); InventoryManipulator.removeById(c, setupInventory, 3994103, 20, false, false); InventoryManipulator.removeById(c, setupInventory, 3994104, 20, false, false); InventoryManipulator.removeById(c, setupInventory, 3994105, 20, false, false); } else { InventoryManipulator.addById(c, 2430007, (short) 1); // Blank // Compass } NpcScriptManager.getInstance().start(c, 2084001); break; } case 2430008: { // Gold Compass chr.saveLocation(SavedLocationType.RICHIE); GameMap map; boolean warped = false; for (int i = 390001000; i <= 390001004; i++) { map = ChannelServer.getMapFactory().getMap(i); if (map.getCharacterCount() == 0) { chr.changeMap(map, map.getPortal(0)); warped = true; break; } } if (warped) { InventoryManipulator.removeById(c, useInventory, 2430008, 1, false, false); } else { c.getPlayer().sendNotice(5, "All maps are currently in use, please try again later."); } break; } } } c.write(ChannelPackets.enableActions()); } public static void handleUseSummonBag(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { if (!chr.isAlive()) { c.write(ChannelPackets.enableActions()); return; } reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final Inventory useInventory = chr.getUseInventory(); final Item toUse = useInventory.getItem(slot); if (toUse != null && toUse.getQuantity() >= 1 && toUse.getItemId() == itemId) { InventoryManipulator.removeFromSlot(c, useInventory, slot, (short) 1, false); if (c.getPlayer().isGM() || !FieldLimitType.SummoningBag.check(chr.getMap().getFieldLimit())) { final List<IdProbabilityEntry> toSpawn = ItemInfoProvider.getInstance().getSummonMobs(itemId); if (toSpawn == null) { c.write(ChannelPackets.enableActions()); return; } Monster ht; final int type = 0; for (int i = 0; i < toSpawn.size(); i++) { if (Randomizer.nextInt(99) <= toSpawn.get(i).Probability) { ht = LifeFactory.getMonster(toSpawn.get(i).Id); chr.getMap().spawnMonster_sSack(ht, chr.getPosition(), type); } } } } c.write(ChannelPackets.enableActions()); } public static void handleUseTreasureChest(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { final short slot = reader.readShort(); final int itemid = reader.readInt(); final Inventory etcInventory = chr.getEtcInventory(); final Item toUse = etcInventory.getItem((byte) slot); if (toUse == null || toUse.getQuantity() <= 0 || toUse.getItemId() != itemid) { c.write(ChannelPackets.enableActions()); return; } int reward; int keyIDforRemoval = 0; switch (toUse.getItemId()) { case 4280000: // Gold box reward = RandomRewards.getInstance().getGoldBoxReward(); keyIDforRemoval = 5490000; break; case 4280001: // Silver box reward = RandomRewards.getInstance().getSilverBoxReward(); keyIDforRemoval = 5490001; break; default: // Up to no good c.disconnect(true); return; } // Get the quantity int amount = 1; switch (reward) { case 2000004: amount = 200; // Elixir break; case 2000005: amount = 100; // Power Elixir break; } final Inventory cashInventory = chr.getCashInventory(); if (cashInventory.countById(keyIDforRemoval) > 0) { final Item item = InventoryManipulator.addbyId_Gachapon(c, reward, (short) amount); if (item == null) { chr.sendNotice(5, "Please check your item inventory and see if you have a Master Key, or if the inventory is full."); c.write(ChannelPackets.enableActions()); return; } InventoryManipulator.removeFromSlot(c, etcInventory, (byte) slot, (short) 1, true); InventoryManipulator.removeById(c, cashInventory, keyIDforRemoval, 1, true, false); c.write(ChannelPackets.getShowItemGain(reward, (short) amount, true)); if (GameConstants.gachaponRareItem(item.getItemId()) > 0) { try { ChannelServer.getWorldInterface().broadcastMessage( ChannelPackets.getGachaponMega(c.getPlayer().getName(), " : Lucky winner of Gachapon! Congratulations~", item, (byte) 2)); } catch (final RemoteException e) { ChannelServer.pingWorld(); } } } else { chr.sendNotice(5, "Please check your item inventory and see if you have a Master Key, or if the inventory is full."); c.write(ChannelPackets.enableActions()); } } public static void handleUseCashItem(final PacketReader reader, final ChannelClient c) throws PacketFormatException { reader.skip(4); final byte slot = (byte) reader.readShort(); final int itemId = reader.readInt(); final ChannelCharacter player = c.getPlayer(); final Item toUse = player.getCashInventory().getItem(slot); if (toUse == null || toUse.getItemId() != itemId || toUse.getQuantity() < 1) { c.write(ChannelPackets.enableActions()); return; } boolean used = false; switch (itemId) { case 5043000: { // NPC Teleport Rock final short questid = reader.readShort(); final int npcid = reader.readInt(); final QuestInfo quest = QuestInfoProvider.getInfo(questid); if (player.getQuestStatus(questid).getState() == 1 && quest.canComplete(player, npcid)) { final GameMap map = ChannelServer.getMapFactory().getMap(LifeFactory.getNpcLocation(npcid)); if (map.containsNPC(npcid) != -1) { player.changeMap(map, map.getPortal(0)); } used = true; } break; } case 2320000: // The Teleport Rock case 5041000: // VIP Teleport Rock case 5040000: // The Teleport Rock case 5040001: { // Teleport Coke if (reader.readByte() == 0) { // Rocktype final GameMap target = ChannelServer.getMapFactory().getMap(reader.readInt()); if (!FieldLimitType.VipRock.check(player.getMap().getFieldLimit())) { // Makes sure this map doesn't have a forced return map player.changeMap(target, target.getPortal(0)); used = true; } } else { final ChannelCharacter victim = ChannelServer.getPlayerStorage().getCharacterByName(reader.readLengthPrefixedString()); if (victim != null && !victim.isGM()) { if (!FieldLimitType.VipRock.check(ChannelServer.getMapFactory().getMap(victim.getMapId()).getFieldLimit())) { if (itemId == 5041000 || victim.getMapId() / 100000000 == player.getMapId() / 100000000) { // Viprock or same continent player.changeMap(victim.getMap(), victim.getMap().findClosestSpawnpoint(victim.getPosition())); used = true; } } } } break; } case 5050000: { // AP Reset final List<StatValue> statupdate = Lists.newArrayListWithCapacity(2); final int apto = reader.readInt(); final int apfrom = reader.readInt(); if (apto == apfrom) { break; // Hack } final int job = player.getJobId(); final ActivePlayerStats playerst = player.getStats(); used = true; switch (apto) { // AP to case 64: // str if (playerst.getStr() >= 999) { used = false; } break; case 128: // dex if (playerst.getDex() >= 999) { used = false; } break; case 256: // int if (playerst.getInt() >= 999) { used = false; } break; case 512: // luk if (playerst.getLuk() >= 999) { used = false; } break; case 2048: // hp if (playerst.getMaxHp() >= 30000) { used = false; } break; case 8192: // mp if (playerst.getMaxMp() >= 30000) { used = false; } break; } switch (apfrom) { // AP to case 64: // str if (playerst.getStr() <= 4) { used = false; } break; case 128: // dex if (playerst.getDex() <= 4) { used = false; } break; case 256: // int if (playerst.getInt() <= 4) { used = false; } break; case 512: // luk if (playerst.getLuk() <= 4) { used = false; } break; case 2048: // hp if (/* * playerst.getMaxMp() < ((c.getPlayer().getLevel() * 14) + * 134) || */player.getHpApUsed() <= 0 || player.getHpApUsed() >= 10000) { used = false; } break; case 8192: // mp if (/* * playerst.getMaxMp() < ((c.getPlayer().getLevel() * 14) + * 134) || */player.getHpApUsed() <= 0 || player.getHpApUsed() >= 10000) { used = false; } break; } if (used) { switch (apto) { // AP to case 64: { // str final int toSet = playerst.getStr() + 1; playerst.setStr(toSet); statupdate.add(new StatValue(Stat.STR, toSet)); break; } case 128: { // dex final int toSet = playerst.getDex() + 1; playerst.setDex(toSet); statupdate.add(new StatValue(Stat.DEX, toSet)); break; } case 256: { // int final int toSet = playerst.getInt() + 1; playerst.setInt(toSet); statupdate.add(new StatValue(Stat.INT, toSet)); break; } case 512: { // luk final int toSet = playerst.getLuk() + 1; playerst.setLuk(toSet); statupdate.add(new StatValue(Stat.LUK, toSet)); break; } case 2048: // hp int maxhp = playerst.getMaxHp(); if (job == 0) { // Beginner maxhp += Randomizer.rand(8, 12); } else if (job >= 100 && job <= 132) { // Warrior final ISkill improvingMaxHP = SkillInfoProvider.getSkill(1000001); final int improvingMaxHPLevel = player.getCurrentSkillLevel(improvingMaxHP); maxhp += Randomizer.rand(20, 25); if (improvingMaxHPLevel >= 1) { maxhp += improvingMaxHP.getEffect(improvingMaxHPLevel).getY(); } } else if (job >= 200 && job <= 232) { // Magician maxhp += Randomizer.rand(10, 20); } else if (job >= 300 && job <= 322) { // Bowman maxhp += Randomizer.rand(16, 20); } else if (job >= 400 && job <= 434) { // Thief maxhp += Randomizer.rand(16, 20); } else if (job >= 500 && job <= 522) { // Pirate final ISkill improvingMaxHP = SkillInfoProvider.getSkill(5100000); final int improvingMaxHPLevel = player.getCurrentSkillLevel(improvingMaxHP); maxhp += 20; if (improvingMaxHPLevel >= 1) { maxhp += improvingMaxHP.getEffect(improvingMaxHPLevel).getY(); } } else if (job >= 1100 && job <= 1111) { // Soul Master final ISkill improvingMaxHP = SkillInfoProvider.getSkill(11000000); final int improvingMaxHPLevel = player.getCurrentSkillLevel(improvingMaxHP); maxhp += Randomizer.rand(36, 42); if (improvingMaxHPLevel >= 1) { maxhp += improvingMaxHP.getEffect(improvingMaxHPLevel).getY(); } } else if (job >= 1200 && job <= 1211) { // Flame Wizard maxhp += Randomizer.rand(15, 21); } else if (job >= 1300 && job <= 1311 || job >= 1400 && job <= 1411) { // Wind // Breaker // and // Night // Walker maxhp += Randomizer.rand(30, 36); } else if (job >= 2000 && job <= 2112) { // Aran maxhp += Randomizer.rand(20, 25); } else { // GameMaster maxhp += Randomizer.rand(50, 100); } maxhp = Math.min(30000, maxhp); player.setHpApUsed(player.getHpApUsed() + 1); playerst.setMaxHp(maxhp); statupdate.add(new StatValue(Stat.HP, maxhp)); break; case 8192: // mp int maxmp = playerst.getMaxMp(); if (job == 0) { // Beginner maxmp += Randomizer.rand(6, 8); } else if (job >= 100 && job <= 132) { maxmp += Randomizer.rand(2, 4); } else if (job >= 200 && job <= 232) { final ISkill improvingMaxMP = SkillInfoProvider.getSkill(2000001); final int improvingMaxMPLevel = player.getCurrentSkillLevel(improvingMaxMP); maxmp += Randomizer.rand(18, 20); if (improvingMaxMPLevel >= 1) { maxmp += improvingMaxMP.getEffect(improvingMaxMPLevel).getY(); } } else if (job >= 300 && job <= 322) { maxmp += Randomizer.rand(10, 12); } else if (job >= 400 && job <= 434) { maxmp += Randomizer.rand(10, 12); } else if (job >= 500 && job <= 522) { maxmp += Randomizer.rand(10, 12); } else if (job >= 1100 && job <= 1111) { maxmp += Randomizer.rand(6, 9); } else if (job >= 1200 && job <= 1211) { final ISkill improvingMaxMP = SkillInfoProvider.getSkill(12000000); final int improvingMaxMPLevel = player.getCurrentSkillLevel(improvingMaxMP); maxmp += Randomizer.rand(33, 36); if (improvingMaxMPLevel >= 1) { maxmp += improvingMaxMP.getEffect(improvingMaxMPLevel).getY(); } } else if (job >= 1300 && job <= 1311 || job >= 1400 && job <= 1411) { maxmp += Randomizer.rand(21, 24); } else if (job >= 2000 && job <= 2112) { maxmp += Randomizer.rand(4, 6); } else { maxmp += Randomizer.rand(50, 100); } maxmp = Math.min(30000, maxmp); player.setMpApUsed(player.getMpApUsed() + 1); playerst.setMaxMp(maxmp); statupdate.add(new StatValue(Stat.MP, maxmp)); break; } switch (apfrom) { // AP from case 64: { // str final int toSet = playerst.getStr() - 1; playerst.setStr(toSet); statupdate.add(new StatValue(Stat.STR, toSet)); break; } case 128: { // dex final int toSet = playerst.getDex() - 1; playerst.setDex(toSet); statupdate.add(new StatValue(Stat.DEX, toSet)); break; } case 256: { // int final int toSet = playerst.getInt() - 1; playerst.setInt(toSet); statupdate.add(new StatValue(Stat.INT, toSet)); break; } case 512: { // luk final int toSet = playerst.getLuk() - 1; playerst.setLuk(toSet); statupdate.add(new StatValue(Stat.LUK, toSet)); break; } case 2048: // HP int maxhp = playerst.getMaxHp(); if (job == 0) { // Beginner maxhp -= 12; } else if (job >= 100 && job <= 132) { // Warrior final ISkill improvingMaxHP = SkillInfoProvider.getSkill(1000001); final int improvingMaxHPLevel = player.getCurrentSkillLevel(improvingMaxHP); maxhp -= 24; if (improvingMaxHPLevel >= 1) { maxhp -= improvingMaxHP.getEffect(improvingMaxHPLevel).getY(); } } else if (job >= 200 && job <= 232) { // Magician maxhp -= 10; } else if (job >= 300 && job <= 322 || job >= 400 && job <= 434) { // Bowman, Thief maxhp -= 15; } else if (job >= 500 && job <= 522) { // Pirate final ISkill improvingMaxHP = SkillInfoProvider.getSkill(5100000); final int improvingMaxHPLevel = player.getCurrentSkillLevel(improvingMaxHP); maxhp -= 15; if (improvingMaxHPLevel > 0) { maxhp -= improvingMaxHP.getEffect(improvingMaxHPLevel).getY(); } } else if (job >= 1100 && job <= 1111) { // Soul Master final ISkill improvingMaxHP = SkillInfoProvider.getSkill(11000000); final int improvingMaxHPLevel = player.getCurrentSkillLevel(improvingMaxHP); maxhp -= 27; if (improvingMaxHPLevel >= 1) { maxhp -= improvingMaxHP.getEffect(improvingMaxHPLevel).getY(); } } else if (job >= 1200 && job <= 1211) { // Flame Wizard maxhp -= 12; } else if (job >= 1300 && job <= 1311 || job >= 1400 && job <= 1411) { // Wind Breaker and Night Walker maxhp -= 17; } else if (job >= 2000 && job <= 2112) { // Aran maxhp -= 20; } else { // GameMaster maxhp -= 20; } player.setHpApUsed(player.getHpApUsed() - 1); playerst.setHp(maxhp); playerst.setMaxHp(maxhp); statupdate.add(new StatValue(Stat.HP, maxhp)); break; case 8192: // MP int maxmp = playerst.getMaxMp(); if (job == 0) { // Beginner maxmp -= 8; } else if (job >= 100 && job <= 132) { // Warrior maxmp -= 4; } else if (job >= 200 && job <= 232) { // Magician final ISkill improvingMaxMP = SkillInfoProvider.getSkill(2000001); final int improvingMaxMPLevel = player.getCurrentSkillLevel(improvingMaxMP); maxmp -= 20; if (improvingMaxMPLevel >= 1) { maxmp -= improvingMaxMP.getEffect(improvingMaxMPLevel).getY(); } } else if (job >= 500 && job <= 522 || job >= 300 && job <= 322 || job >= 400 && job <= 434) { // Pirate, // Bowman. // Thief maxmp -= 10; } else if (job >= 1100 && job <= 1111) { // Soul Master maxmp -= 6; } else if (job >= 1200 && job <= 1211) { // Flame Wizard final ISkill improvingMaxMP = SkillInfoProvider.getSkill(12000000); final int improvingMaxMPLevel = player.getCurrentSkillLevel(improvingMaxMP); maxmp -= 25; if (improvingMaxMPLevel >= 1) { maxmp -= improvingMaxMP.getEffect(improvingMaxMPLevel).getY(); } } else if (job >= 1300 && job <= 1311 || job >= 1400 && job <= 1411) { // Wind // Breaker // and // Night // Walker maxmp -= 15; } else if (job >= 2000 && job <= 2112) { // Aran maxmp -= 5; } else { // GameMaster maxmp -= 20; } player.setMpApUsed(player.getMpApUsed() - 1); playerst.setMp(maxmp); playerst.setMaxMp(maxmp); statupdate.add(new StatValue(Stat.MP, maxmp)); break; } c.write(ChannelPackets.updatePlayerStats(statupdate, true, player.getJobId())); } break; } case 5050005: case 5050006: case 5050007: case 5050008: case 5050009: case 5050001: // SP Reset (1st job) case 5050002: // SP Reset (2nd job) case 5050003: // SP Reset (3rd job) case 5050004: { // SP Reset (4th job) final int skill1 = reader.readInt(); final int skill2 = reader.readInt(); final ISkill skillSPTo = SkillInfoProvider.getSkill(skill1); final ISkill skillSPFrom = SkillInfoProvider.getSkill(skill2); if (skillSPTo.isBeginnerSkill() || skillSPFrom.isBeginnerSkill()) { break; } if (player.getCurrentSkillLevel(skillSPTo) + 1 <= skillSPTo.getMaxLevel() && player.getCurrentSkillLevel(skillSPFrom) > 0) { player.changeSkillLevel(skillSPFrom, (byte) (player.getCurrentSkillLevel(skillSPFrom) - 1), player.getMasterSkillLevel(skillSPFrom)); player.changeSkillLevel(skillSPTo, (byte) (player.getCurrentSkillLevel(skillSPTo) + 1), player.getMasterSkillLevel(skillSPTo)); used = true; } break; } case 5060000: { // Item Tag final Item item = player.getEquippedItemsInventory().getItem(reader.readByte()); if (item != null && item.getOwner().equals("")) { item.setOwner(player.getName()); used = true; } break; } case 5520001: case 5520000: { // Karma final byte typeByte = (byte) reader.readInt(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = player.getInventoryByType(type); final Item item = inventory.getItem((byte) reader.readInt()); if (item != null) { if (ItemInfoProvider.getInstance().isKarmaEnabled(item.getItemId(), itemId)) { byte flag = item.getFlag(); if (inventory.getType() == InventoryType.EQUIP) { flag |= ItemFlag.KARMA_EQ.getValue(); } else { flag |= ItemFlag.KARMA_USE.getValue(); } item.setFlag(flag); c.write(ChannelPackets.updateSpecialItemUse(item, inventory.getType().asNumber())); used = true; } } break; } case 5570000: { // Vicious Hammer final byte invType = (byte) reader.readInt(); // Inventory type, // Hammered eq is // always EQ. final Equip item = (Equip) player.getEquipInventory().getItem((byte) reader.readInt()); // another int here, D3 49 DC 00 if (item != null) { if (item.getViciousHammer() <= 2) { item.setViciousHammer((byte) (item.getViciousHammer() + 1)); item.setUpgradeSlots((byte) (item.getUpgradeSlots() + 1)); c.write(ChannelPackets.updateSpecialItemUse(item, invType)); // c.write(MTSCSPacket.ViciousHammer(true, (byte) // item.getViciousHammer())); // c.write(MTSCSPacket.ViciousHammer(false, (byte) 0)); used = true; } } break; } case 5060001: { // Sealing Lock final byte typeByte = (byte) reader.readInt(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = player.getInventoryByType(type); final Item item = inventory.getItem((byte) reader.readInt()); // another int here, lock = 5A E5 F2 0A, 7 day = D2 30 F3 0A if (item != null && item.getExpiration() == -1) { byte flag = item.getFlag(); flag |= ItemFlag.LOCK.getValue(); item.setFlag(flag); c.write(ChannelPackets.updateSpecialItemUse(item, typeByte)); used = true; } break; } case 5061000: { // Sealing Lock 7 days final byte typeByte = (byte) reader.readInt(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = player.getInventoryByType(type); final Item item = inventory.getItem((byte) reader.readInt()); // another int here, lock = 5A E5 F2 0A, 7 day = D2 30 F3 0A if (item != null && item.getExpiration() == -1) { byte flag = item.getFlag(); flag |= ItemFlag.LOCK.getValue(); item.setFlag(flag); item.setExpiration(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000); c.write(ChannelPackets.updateSpecialItemUse(item, typeByte)); used = true; } break; } case 5061001: { // Sealing Lock 30 days final byte typeByte = (byte) reader.readInt(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = player.getInventoryByType(type); final Item item = inventory.getItem((byte) reader.readInt()); // another int here, lock = 5A E5 F2 0A, 7 day = D2 30 F3 0A if (item != null && item.getExpiration() == -1) { byte flag = item.getFlag(); flag |= ItemFlag.LOCK.getValue(); item.setFlag(flag); item.setExpiration(System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000); c.write(ChannelPackets.updateSpecialItemUse(item, typeByte)); used = true; } break; } case 5061002: { // Sealing Lock 90 days final byte typeByte = (byte) reader.readInt(); final InventoryType type = InventoryType.fromNumber(typeByte); final Inventory inventory = player.getInventoryByType(type); final Item item = inventory.getItem((byte) reader.readInt()); // another int here, lock = 5A E5 F2 0A, 7 day = D2 30 F3 0A if (item != null && item.getExpiration() == -1) { byte flag = item.getFlag(); flag |= ItemFlag.LOCK.getValue(); item.setFlag(flag); item.setExpiration(System.currentTimeMillis() + 90 * 24 * 60 * 60 * 1000); c.write(ChannelPackets.updateSpecialItemUse(item, typeByte)); used = true; } break; } case 5071000: { // Megaphone if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final String message = reader.readLengthPrefixedString(); if (message.length() > 65) { break; } final StringBuilder sb = new StringBuilder(); addMedalString(player, sb); sb.append(player.getName()); sb.append(" : "); sb.append(message); player.getMap().broadcastMessage(ChannelPackets.serverNotice(2, sb.toString())); used = true; } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5077000: { // 3 line Megaphone if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final byte numLines = reader.readByte(); if (numLines > 3) { return; } final List<String> messages = Lists.newLinkedList(); String message; for (int i = 0; i < numLines; i++) { message = reader.readLengthPrefixedString(); if (message.length() > 65) { break; } messages.add(player.getName() + " : " + message); } final boolean ear = reader.readByte() > 0; try { ChannelServer.getWorldInterface().broadcastSmega(ChannelPackets.tripleSmega(messages, ear, c.getChannelId())); used = true; } catch (final RemoteException e) { System.out.println("RemoteException occured, triple megaphone"); } } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5073000: { // Heart Megaphone if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final String message = reader.readLengthPrefixedString(); if (message.length() > 65) { break; } final StringBuilder sb = new StringBuilder(); addMedalString(player, sb); sb.append(player.getName()); sb.append(" : "); sb.append(message); final boolean ear = reader.readByte() != 0; try { ChannelServer.getWorldInterface().broadcastSmega(ChannelPackets.serverNotice(9, c.getChannelId(), sb.toString(), ear)); used = true; } catch (final RemoteException e) { System.out.println("RemoteException occured, heart megaphone"); } } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5074000: { // Skull Megaphone if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final String message = reader.readLengthPrefixedString(); if (message.length() > 65) { break; } final StringBuilder sb = new StringBuilder(); addMedalString(player, sb); sb.append(player.getName()); sb.append(" : "); sb.append(message); final boolean ear = reader.readByte() != 0; try { ChannelServer.getWorldInterface().broadcastSmega(ChannelPackets.serverNotice(10, c.getChannelId(), sb.toString(), ear)); used = true; } catch (final RemoteException e) { System.out.println("RemoteException occured, skull megaphone"); } } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5072000: { // Super Megaphone if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final String message = reader.readLengthPrefixedString(); if (message.length() > 65) { break; } final StringBuilder sb = new StringBuilder(); addMedalString(player, sb); sb.append(player.getName()); sb.append(" : "); sb.append(message); final boolean ear = reader.readByte() != 0; try { ChannelServer.getWorldInterface().broadcastSmega(ChannelPackets.serverNotice(3, c.getChannelId(), sb.toString(), ear)); used = true; } catch (final RemoteException e) { System.out.println("RemoteException occured, super megaphone"); } } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5076000: { // Item Megaphone if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final String message = reader.readLengthPrefixedString(); if (message.length() > 65) { break; } final StringBuilder sb = new StringBuilder(); addMedalString(player, sb); sb.append(player.getName()); sb.append(" : "); sb.append(message); final boolean ear = reader.readByte() > 0; Item item = null; if (reader.readByte() == 1) { // item final byte typeByte = (byte) reader.readInt(); final byte pos = (byte) reader.readInt(); final InventoryType type = InventoryType.fromNumber(typeByte); item = player.getInventoryByType(type).getItem(pos); } try { ChannelServer.getWorldInterface().broadcastSmega(ChannelPackets.itemMegaphone(sb.toString(), ear, c.getChannelId(), item)); used = true; } catch (final RemoteException e) { System.out.println("RemoteException occured, item megaphone"); } } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5075000: // MapleTV Messenger case 5075001: // MapleTV Star Messenger case 5075002: // MapleTV Heart Messenger break; case 5090100: // Wedding Invitation Card case 5090000: { // Note final String sendTo = reader.readLengthPrefixedString(); final String msg = reader.readLengthPrefixedString(); player.sendNote(sendTo, msg); used = true; break; } case 5100000: { // Congratulatory Song player.getMap().broadcastMessage(ChannelPackets.musicChange("Jukebox/Congratulation")); used = true; break; } case 5170000: { // Pet name change if (player.getPet(0) == null) { break; } final String nName = reader.readLengthPrefixedString(); if (GameCharacterUtil.validatePetName(nName)) { player.getPet(0).setName(nName); c.write(PetPacket.updatePet(player.getPet(0), true)); c.write(ChannelPackets.enableActions()); player.getMap().broadcastMessage(player, MTSCSPacket.changePetName(player, nName, 1), true); used = true; } break; } case 5200000: { // Bronze Sack of Mesos player.gainMeso(1000000, true, false, true); c.write(ChannelPackets.enableActions()); used = true; break; } case 5200001: { // Silver Sack of Mesos player.gainMeso(5000000, true, false, true); c.write(ChannelPackets.enableActions()); used = true; break; } case 5200002: { // Gold Sack of Mesos player.gainMeso(10000000, true, false, true); c.write(ChannelPackets.enableActions()); used = true; break; } case 5240000: case 5240001: case 5240002: case 5240003: case 5240004: case 5240005: case 5240006: case 5240007: case 5240008: case 5240009: case 5240010: case 5240011: case 5240012: case 5240013: case 5240014: case 5240015: case 5240016: case 5240017: case 5240018: case 5240019: case 5240020: case 5240021: case 5240022: case 5240023: case 5240025: case 5240026: case 5240027: case 5240028: case 5240024: { // Pet food Pet pet = player.getPet(0); if (pet == null) { break; } if (!pet.canConsume(itemId)) { pet = player.getPet(1); if (pet != null) { if (!pet.canConsume(itemId)) { pet = player.getPet(2); if (pet != null) { if (!pet.canConsume(itemId)) { break; } } else { break; } } } else { break; } } final byte petindex = player.getPetIndex(pet); pet.setFullness(100); if (pet.getCloseness() < 30000) { if (pet.getCloseness() + 100 > 30000) { pet.setCloseness(30000); } else { pet.setCloseness(pet.getCloseness() + 100); } if (pet.getCloseness() >= GameConstants.getClosenessNeededForLevel(pet.getLevel() + 1)) { pet.setLevel(pet.getLevel() + 1); c.write(PetPacket.showOwnPetLevelUp(player.getPetIndex(pet))); player.getMap().broadcastMessage(PetPacket.showPetLevelUp(player, petindex)); } } c.write(PetPacket.updatePet(pet, true)); player.getMap().broadcastMessage(player, PetPacket.commandResponse(player.getId(), (byte) 1, petindex, true, true), true); used = true; break; } // case 5280001: // Gas Skill case 5281000: { // Passed gas /* * Rectangle bounds = new Rectangle((int) * c.getPlayer().getPosition().getX(), (int) * c.getPlayer().getPosition().getY(), 1, 1); MapleStatEffect mse = * new MapleStatEffect(); mse.setSourceId(2111003); MapleMist mist = * new MapleMist(bounds, c.getPlayer(), mse); * c.getPlayer().getMap().spawnMist(mist, 10000, false, true); * c.getPlayer().getMap().broadcastMessage(MaplePacketCreator. * getChatText (c.getPlayer().getId(), "Oh no, I farted!", false, * 1)); c.write(MaplePacketCreator.enableActions()); used = true; */ break; } case 5370000: { // Chalkboard player.setChalkboard(reader.readLengthPrefixedString()); break; } case 5370001: { // BlackBoard if (player.getMapId() / 1000000 == 910) { player.setChalkboard(reader.readLengthPrefixedString()); } break; } case 5390000: // Diablo Messenger case 5390001: // Cloud 9 Messenger case 5390002: // Loveholic Messenger case 5390003: // New Year Megassenger 1 case 5390004: // New Year Megassenger 2 case 5390005: // Cute Tiger Messenger case 5390006: { // Tiger Roar's Messenger if (!ChannelServer.getInstance().getMegaphoneMuteState()) { final String text = reader.readLengthPrefixedString(); if (text.length() > 55) { break; } final boolean ear = reader.readByte() != 0; try { ChannelServer.getWorldInterface().broadcastSmega(ChannelPackets.getAvatarMega(player, c.getChannelId(), itemId, text, ear)); used = true; } catch (final RemoteException e) { System.out.println("RemoteException occured, TV megaphone"); } } else { player.sendNotice(5, "The usage of Megapone is currently disabled."); } break; } case 5450000: { // Mu Mu the Travelling Merchant ShopFactory.getInstance().getShop(61).sendShop(c); used = true; break; } default: if (itemId / 10000 == 512) { final ItemInfoProvider ii = ItemInfoProvider.getInstance(); final String msg = ii.getMsg(itemId).replaceFirst("%s", player.getName()).replaceFirst("%s", reader.readLengthPrefixedString()); player.getMap().startMapEffect(msg, itemId); final int buff = ii.getStateChangeItem(itemId); if (buff != 0) { for (final ChannelCharacter mChar : player.getMap().getCharacters()) { ii.getItemEffect(buff).applyTo(mChar); } } used = true; } else { System.out.println(":: Unhandled CS item : " + itemId + " ::"); System.out.println(reader.toString()); } break; } if (used) { InventoryManipulator.removeById(c, player.getCashInventory(), itemId, 1, true, false); } else { c.write(ChannelPackets.enableActions()); } } public static void handleItemLoot(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { reader.skip(5); // [4] Seems to be tickcount, [1] always 0 final Point Client_Reportedpos = reader.readVector(); final GameMapObject ob = chr.getMap().getMapObject(reader.readInt()); if (ob == null || ob.getType() != GameMapObjectType.ITEM) { c.write(ChannelPackets.enableActions()); return; } final GameMapItem mapItem = (GameMapItem) ob; if (mapItem.isPickedUp()) { c.write(ChannelPackets.enableActions()); return; } if (mapItem.getOwner() != chr.getId() && chr.getMap().isEverlast()) { c.write(ChannelPackets.enableActions()); return; } final double Distance = Client_Reportedpos.distanceSq(mapItem.getPosition()); if (Distance > 2500) { chr.getCheatTracker().registerOffense(CheatingOffense.ITEMVAC_CLIENT, String.valueOf(Distance)); } else if (chr.getPosition().distanceSq(mapItem.getPosition()) > 90000.0) { chr.getCheatTracker().registerOffense(CheatingOffense.ITEMVAC_SERVER); } if (mapItem.getMeso() > 0) { final PartyMember member = chr.getPartyMembership(); if (member != null && mapItem.getOwner() == chr.getId()) { final List<ChannelCharacter> toGive = Lists.newLinkedList(); final ChannelServer channelServer = ChannelServer.getInstance(); final Party party = chr.getParty(); for (final ChannelCharacter m : channelServer.getPartyMembers(party.getId())) { // TODO, store info in MaplePartyCharacter instead if (m != null) { if (m.getMapId() == chr.getMapId()) { toGive.add(m); } } } for (final ChannelCharacter m : toGive) { m.gainMeso(mapItem.getMeso() / toGive.size(), true, true); } } else { chr.gainMeso(mapItem.getMeso(), true, true); } removeItem(chr, mapItem, ob); } else { if (GameConstants.isUseableItem(mapItem.getItemId())) { useItem(c, mapItem.getItemId()); removeItem(c.getPlayer(), mapItem, ob); } else if (InventoryManipulator.addFromDrop(c, mapItem.getItem(), true)) { removeItem(chr, mapItem, ob); } } } public static void handlePetLoot(final PacketReader reader, final ChannelClient c, final ChannelCharacter chr) throws PacketFormatException { final Pet pet = chr.getPet(chr.getPetIndex(reader.readInt())); reader.skip(9); // [4] Zero, [4] Seems to be tickcount, [1] Always zero final Point Client_Reportedpos = reader.readVector(); final GameMapObject ob = chr.getMap().getMapObject(reader.readInt()); if (ob == null || pet == null || ob.getType() != GameMapObjectType.ITEM) { return; } final GameMapItem mapitem = (GameMapItem) ob; if (mapitem.isPickedUp()) { c.write(ChannelPackets.getInventoryFull()); return; } if (mapitem.getOwner() != chr.getId() || mapitem.isPlayerDrop()) { return; } final double Distance = Client_Reportedpos.distanceSq(mapitem.getPosition()); if (Distance > 2500) { chr.getCheatTracker().registerOffense(CheatingOffense.PET_ITEMVAC_CLIENT, String.valueOf(Distance)); } else if (pet.getPosition().distanceSq(mapitem.getPosition()) > 90000.0) { chr.getCheatTracker().registerOffense(CheatingOffense.PET_ITEMVAC_SERVER); } if (mapitem.getMeso() > 0) { if (chr.getEquippedItemsInventory().findById(1812000) == null) { c.write(ChannelPackets.enableActions()); return; } if (chr.getParty() != null && mapitem.getOwner() == chr.getId()) { final List<ChannelCharacter> toGive = Lists.newLinkedList(); for (final ChannelCharacter m : ChannelServer.getInstance().getPartyMembers(chr.getParty().getId())) { // TODO, store info in MaplePartyCharacter instead if (m != null) { if (m.getMapId() == chr.getMapId()) { toGive.add(m); } } } for (final ChannelCharacter m : toGive) { m.gainMeso(mapitem.getMeso() / toGive.size(), true, true); } } else { chr.gainMeso(mapitem.getMeso(), true, true); } removeItem(chr, mapitem, ob); } else { if (GameConstants.isUseableItem(mapitem.getItemId())) { useItem(c, mapitem.getItemId()); removeItem(chr, mapitem, ob); } else { if (InventoryManipulator.addFromDrop(c, mapitem.getItem(), true)) { removeItem(chr, mapitem, ob); } } } } private static void useItem(final ChannelClient c, final int id) { if (!GameConstants.isUseableItem(id)) { throw new IllegalArgumentException("Parameter 'id' is not an id of a useable item."); } final ItemInfoProvider ii = ItemInfoProvider.getInstance(); final ItemConsumeType type = ii.isConsumeOnPickup(id); final ChannelCharacter player = c.getPlayer(); switch (type) { case ON_PICKUP_PARTY: if (player.getParty() != null) { for (final PartyMember pc : player.getParty().getMembers()) { final ChannelCharacter chr = player.getMap().getCharacterById_InMap(pc.getCharacterId()); if (chr != null) { ii.getItemEffect(id).applyTo(chr); } } } else { ii.getItemEffect(id).applyTo(player); } break; case ON_PICKUP: ii.getItemEffect(id).applyTo(player); break; } } private static void removeItem(final ChannelCharacter chr, final GameMapItem mapitem, final GameMapObject ob) { mapitem.setPickedUp(true); chr.getMap().broadcastMessage(ChannelPackets.removeItemFromMap(mapitem.getObjectId(), 2, chr.getId()), mapitem.getPosition()); chr.getMap().removeMapObject(ob); } private static void addMedalString(final ChannelCharacter c, final StringBuilder sb) { final Item medal = c.getEquippedItemsInventory().getItem((byte) -46); if (medal != null) { // Medal sb.append("<"); sb.append(ItemInfoProvider.getInstance().getName(medal.getItemId())); sb.append("> "); } } }