/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.handlers.channel;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import constants.ExpTable;
import client.IEquip;
import client.IItem;
import client.ISkill;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleInventoryType;
import client.MapleJob;
import client.MaplePet;
import client.MapleStat;
import client.MapleStatDelta;
import client.SkillFactory;
import constants.ItemConstants;
import constants.skills.Aran;
import java.sql.SQLException;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import scripting.npc.NPCScriptManager;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MapleShop;
import server.MapleShopFactory;
import server.maps.MapleMap;
import server.maps.MapleTVEffect;
import tools.MaplePacketCreator;
import tools.Output;
import tools.data.input.SeekableLittleEndianAccessor;
public final class UseCashItemHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter player = c.getPlayer();
if (System.currentTimeMillis() - player.getLastUsedCashItem() < 3000) {
return;
}
player.setLastUsedCashItem(System.currentTimeMillis());
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
slea.readShort();
int itemId = slea.readInt();
int itemType = itemId / 10000;
IItem toUse = c.getPlayer().getInventory(MapleInventoryType.CASH).getItem(c.getPlayer().getInventory(MapleInventoryType.CASH).findById(itemId).getPosition());
String medal = "";
IItem medalItem = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((byte) -49);
if (medalItem != null) {
medal = "<" + ii.getName(medalItem.getItemId()) + "> ";
}
if (toUse == null || toUse.getItemId() != itemId || toUse.getQuantity() < 1) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (itemType == 505) { // AP/SP reset
if (itemId > 5050000) {
int SPTo = slea.readInt();
int SPFrom = slea.readInt();
ISkill skillSPTo = SkillFactory.getSkill(SPTo);
ISkill skillSPFrom = SkillFactory.getSkill(SPFrom);
byte curLevel = player.getSkillLevel(skillSPTo);
byte curLevelSPFrom = player.getSkillLevel(skillSPFrom);
if ((curLevel < skillSPTo.getMaxLevel()) && curLevelSPFrom > 0) {
player.changeSkillLevel(skillSPFrom, (byte) (curLevelSPFrom - 1), player.getMasterLevel(skillSPFrom), -1);
player.changeSkillLevel(skillSPTo, (byte) (curLevel + 1), player.getMasterLevel(skillSPTo), -1);
if (SPFrom == Aran.FULL_SWING) {
ISkill hidden1 = SkillFactory.getSkill(Aran.HIDDEN_FULL_DOUBLE);
ISkill hidden2 = SkillFactory.getSkill(Aran.HIDDEN_FULL_TRIPLE);
player.changeSkillLevel(hidden1, (byte) (curLevelSPFrom - 1), player.getMasterLevel(hidden1), -1);
player.changeSkillLevel(hidden2, (byte) (curLevelSPFrom - 1), player.getMasterLevel(hidden2), -1);
} else if (SPFrom == Aran.OVER_SWING) {
ISkill hidden1 = SkillFactory.getSkill(Aran.HIDDEN_OVER_DOUBLE);
ISkill hidden2 = SkillFactory.getSkill(Aran.HIDDEN_OVER_TRIPLE);
player.changeSkillLevel(hidden1, (byte) (curLevelSPFrom - 1), player.getMasterLevel(hidden1), -1);
player.changeSkillLevel(hidden2, (byte) (curLevelSPFrom - 1), player.getMasterLevel(hidden2), -1);
}
}
} else {
List<MapleStatDelta> statupdate = new ArrayList<MapleStatDelta>(2);
int APTo = slea.readInt();
int APFrom = slea.readInt();
switch (APFrom) {
case 64: // str
if (player.getStr() < 5) {
return;
}
player.addStat(1, -1);
break;
case 128: // dex
if (player.getDex() < 5) {
return;
}
player.addStat(2, -1);
break;
case 256: // int
if (player.getInt() < 5) {
return;
}
player.addStat(3, -1);
break;
case 512: // luk
if (player.getLuk() < 5) {
return;
}
player.addStat(4, -1);
break;
case 2048: // HP
int hplose = 0;
final int jobid = player.getJob().getId();
if (jobid == 0 || jobid == 1000 || jobid == 2000 || jobid >= 1200 && jobid <= 1211) { // Beginner
hplose -= 12;
} else if (jobid >= 100 && jobid <= 132) { // Warrior
ISkill improvinghplose = SkillFactory.getSkill(1000001);
int improvinghploseLevel = c.getPlayer().getSkillLevel(improvinghplose);
hplose -= 24;
if (improvinghploseLevel >= 1) {
hplose -= improvinghplose.getEffect(improvinghploseLevel).getY();
}
} else if (jobid >= 200 && jobid <= 232) { // Magician
hplose -= 10;
} else if (jobid >= 500 && jobid <= 522) { // Pirate
ISkill improvinghplose = SkillFactory.getSkill(5100000);
int improvinghploseLevel = c.getPlayer().getSkillLevel(improvinghplose);
hplose -= 22;
if (improvinghploseLevel > 0) {
hplose -= improvinghplose.getEffect(improvinghploseLevel).getY();
}
} else if (jobid >= 1100 && jobid <= 1111) { // Soul
// Master
ISkill improvinghplose = SkillFactory.getSkill(11000000);
int improvinghploseLevel = c.getPlayer().getSkillLevel(improvinghplose);
hplose -= 27;
if (improvinghploseLevel >= 1) {
hplose -= improvinghplose.getEffect(improvinghploseLevel).getY();
}
} else if ((jobid >= 1300 && jobid <= 1311) || (jobid >= 1400 && jobid <= 1411)) { // Wind
// Breaker
// and
// Night
// Walker
hplose -= 17;
} else if (jobid >= 300 && jobid <= 322 || jobid >= 400 && jobid <= 422 || jobid >= 2000 && jobid <= 2112) { // Aran
hplose -= 20;
} else { // GameMaster
hplose -= 20;
}
player.setHp(player.getHp() + hplose);
player.setMaxHp(player.getMaxHp() + hplose);
statupdate.add(new MapleStatDelta(MapleStat.HP, player.getHp()));
statupdate.add(new MapleStatDelta(MapleStat.MAXHP, player.getMaxHp()));
break;
case 8192: // MP
int mp = player.getMp();
int level = player.getLevel();
MapleJob job = player.getJob();
boolean canWash = true;
if (job.isA(MapleJob.SPEARMAN) && mp < 4 * level + 156) {
canWash = false;
} else if (job.isA(MapleJob.FIGHTER) && mp < 4 * level + 56) {
canWash = false;
} else if (job.isA(MapleJob.THIEF) && job.getId() % 100 > 0 && mp < level * 14 - 4) {
canWash = false;
} else if (mp < level * 14 + 148) {
canWash = false;
}
if (canWash) {
int minmp = 0;
if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1) || job.isA(MapleJob.ARAN1)) {
minmp += 4;
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
minmp += 36;
} else if (job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.WINDARCHER1) || job.isA(MapleJob.THIEF) || job.isA(MapleJob.NIGHTWALKER1)) {
minmp += 12;
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
minmp += 16;
} else {
minmp += 8;
}
player.setMp(player.getMp() - minmp);
player.setMaxMp(player.getMaxMp() - minmp);
statupdate.add(new MapleStatDelta(MapleStat.MP, player.getMp()));
statupdate.add(new MapleStatDelta(MapleStat.MAXMP, player.getMaxMp()));
break;
}
default:
c.announce(MaplePacketCreator.updatePlayerStats(MaplePacketCreator.EMPTY_STATUPDATE, true));
return;
}
DistributeAPHandler.addStat(c, APTo);
c.announce(MaplePacketCreator.updatePlayerStats(statupdate, true));
}
remove(c, itemId);
} else if (itemType == 506) {
IItem eq = null;
if (itemId == 5060000) { // Item tag.
int equipSlot = slea.readShort();
if (equipSlot == 0) {
return;
}
eq = player.getInventory(MapleInventoryType.EQUIPPED).getItem((byte) equipSlot);
eq.setOwner(player.getName());
} else if (itemId == 5060001 || itemId == 5061000 || itemId == 5061001 || itemId == 5061002 || itemId == 5061003) { // Sealing
// lock
MapleInventoryType type = MapleInventoryType.getByType((byte) slea.readInt());
IItem item = c.getPlayer().getInventory(type).getItem((byte) slea.readInt());
if (item == null) { // Check if the type is EQUIPMENT?
return;
}
byte flag = item.getFlag();
flag |= ItemConstants.LOCK;
if (item.getExpiration() > -1) {
return; // No perma items pls
}
item.setFlag(flag);
long period = 0;
if (itemId == 5061000) {
period = 7;
} else if (itemId == 5061001) {
period = 30;
} else if (itemId == 5061002) {
period = 90;
} else if (itemId == 5061003) {
period = 365;
}
if (period > 0) {
item.setExpiration(System.currentTimeMillis() + (period * 60 * 60 * 24 * 1000));
}
c.announce(MaplePacketCreator.updateSlot(item));
remove(c, itemId);
} else if (itemId == 5060002) { // Incubator
byte inventory2 = (byte) slea.readInt();
byte slot2 = (byte) slea.readInt();
IItem item2 = c.getPlayer().getInventory(MapleInventoryType.getByType(inventory2)).getItem(slot2);
if (item2 == null) // hacking
{
return;
}
if (getIncubatedItem(c, itemId)) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.getByType(inventory2), slot2, (short) 1, false);
remove(c, itemId);
}
return;
}
slea.readInt(); // time stamp
c.announce(MaplePacketCreator.updateSlot(eq));
remove(c, itemId);
} else if (itemType == 507) {
boolean whisper;
switch (itemId / 1000 % 10) {
case 1: // Megaphone
if (player.getLevel() > 9) {
player.getClient().getChannelServer().broadcastPacket(MaplePacketCreator.serverNotice(2, medal + player.getName() + " : " + slea.readMapleAsciiString()));
} else {
player.dropMessage(1, "You may not use this until you're level 10.");
}
break;
case 2: // Super megaphone
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.serverNotice(3, c.getChannel(), medal + player.getName() + " : " + slea.readMapleAsciiString(), (slea.readByte() != 0)));
break;
case 5: // Maple TV
int tvType = itemId % 10;
boolean megassenger = false;
boolean ear = false;
MapleCharacter victim = null;
if (tvType != 1) {
if (tvType >= 3) {
megassenger = true;
if (tvType == 3) {
slea.readByte();
}
ear = 1 == slea.readByte();
} else if (tvType != 2) {
slea.readByte();
}
if (tvType != 4) {
victim = c.getChannelServer().getPlayerStorage().getCharacterByName(slea.readMapleAsciiString());
}
}
List<String> messages = new LinkedList<String>();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 5; i++) {
String message = slea.readMapleAsciiString();
if (megassenger) {
builder.append(" ").append(message);
}
messages.add(message);
}
slea.readInt();
if (megassenger) {
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.serverNotice(3, c.getChannel(), medal + player.getName() + " : " + builder.toString(), ear));
}
if (!MapleTVEffect.isActive()) {
new MapleTVEffect(player, victim, messages, tvType, c.getWorld());
remove(c, itemId);
} else {
player.dropMessage(1, "MapleTV is already in use.");
return;
}
break;
case 6: // item megaphone
String msg = medal + c.getPlayer().getName() + " : " + slea.readMapleAsciiString();
whisper = slea.readByte() == 1;
IItem item = null;
if (slea.readByte() == 1) { // item
item = c.getPlayer().getInventory(MapleInventoryType.getByType((byte) slea.readInt())).getItem((byte) slea.readInt());
if (item == null) // hack
{
return;
} else if (ii.isDropRestricted(item.getItemId())) { // Lol?
player.dropMessage(1, "You cannot trade this item.");
c.announce(MaplePacketCreator.enableActions());
return;
}
}
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.itemMegaphone(msg, whisper, c.getChannel(), item));
break;
case 7: // triple megaphone
int lines = slea.readByte();
if (lines < 1 || lines > 3) // hack
{
return;
}
String[] msg2 = new String[lines];
for (int i = 0; i < lines; i++) {
msg2[i] = medal + c.getPlayer().getName() + " : " + slea.readMapleAsciiString();
}
whisper = slea.readByte() == 1;
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.getMultiMegaphone(msg2, c.getChannel(), whisper));
break;
}
remove(c, itemId);
} else if (itemType == 508) { // graduation banner
slea.readMapleAsciiString(); // message, sepearated by 0A for lines
c.announce(MaplePacketCreator.enableActions());
} else if (itemType == 509) {
String sendTo = slea.readMapleAsciiString();
String msg = slea.readMapleAsciiString();
try {
player.sendNote(sendTo, msg, (byte) 0);
} catch (SQLException e) {
}
remove(c, itemId);
} else if (itemType == 510) {
player.getMap().broadcastMessage(MaplePacketCreator.musicChange("Jukebox/Congratulation"));
remove(c, itemId);
} else if (itemType == 512) {
if (ii.getStateChangeItem(itemId) != 0) {
for (MapleCharacter mChar : c.getPlayer().getMap().getCharacters()) {
ii.getItemEffect(ii.getStateChangeItem(itemId)).applyTo(mChar);
}
}
player.getMap().startMapEffect(ii.getMsg(itemId).replaceFirst("%s", c.getPlayer().getName()).replaceFirst("%s", slea.readMapleAsciiString()), itemId);
remove(c, itemId);
} else if (itemType == 517) {
MaplePet pet = player.getPet(0);
if (pet == null) {
c.announce(MaplePacketCreator.enableActions());
return;
}
IItem item = player.getInventory(MapleInventoryType.CASH).getItem(pet.getPosition());
String newName = slea.readMapleAsciiString();
pet.setName(newName);
pet.saveToDb();
c.announce(MaplePacketCreator.updateSlot(item));
player.getMap().broadcastMessage(player, MaplePacketCreator.changePetName(player, newName, 1), true);
c.announce(MaplePacketCreator.enableActions());
remove(c, itemId);
} else if (itemType == 504) { // vip teleport rock
String error1 = "Either the player could not be found or you were trying to teleport to an illegal location.";
boolean vip = slea.readByte() == 1;
remove(c, itemId);
if (!vip) {
int mapId = slea.readInt();
if (c.getChannelServer().getMapFactory().getMap(mapId).getForcedReturnId() == 999999999) {
player.changeMap(c.getChannelServer().getMapFactory().getMap(mapId));
} else {
MapleInventoryManipulator.addById(c, itemId, (short) 1);
c.getPlayer().dropMessage(1, error1);
c.announce(MaplePacketCreator.enableActions());
}
} else {
String name = slea.readMapleAsciiString();
MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(name);
boolean success = false;
if (victim != null) {
MapleMap target = victim.getMap();
if (c.getChannelServer().getMapFactory().getMap(victim.getMapId()).getForcedReturnId() == 999999999 || victim.getMapId() < 100000000) {
if (victim.gmLevel() <= player.gmLevel()) {
if (itemId == 5041000 || victim.getMapId() / player.getMapId() == 1) { // viprock
// &
// same
// continent
player.changeMap(target, target.findClosestSpawnpoint(victim.getPosition()));
success = true;
} else {
player.dropMessage(1, error1);
}
} else {
player.dropMessage(1, error1);
}
} else {
player.dropMessage(1, "You cannot teleport to this map.");
}
} else {
player.dropMessage(1, "Player could not be found in this channel.");
}
if (!success) {
MapleInventoryManipulator.addById(c, itemId, (short) 1);
c.announce(MaplePacketCreator.enableActions());
}
}
} else if (itemType == 520) {
player.gainMeso(ii.getMeso(itemId), true, false, true);
remove(c, itemId);
c.announce(MaplePacketCreator.enableActions());
} else if (itemType == 524) {
for (byte i = 0; i < 3; i++) {
MaplePet pet = player.getPet(i);
if (pet != null) {
if (pet.canConsume(itemId)) {
pet.setFullness(100);
if (pet.getCloseness() + 100 > 30000) {
pet.setCloseness(30000);
} else {
pet.gainCloseness(100);
}
while (pet.getCloseness() >= ExpTable.getClosenessNeededForLevel(pet.getLevel())) {
pet.setLevel((byte) (pet.getLevel() + 1));
byte index = player.getPetIndex(pet);
c.announce(MaplePacketCreator.showOwnPetLevelUp(index));
player.getMap().broadcastMessage(MaplePacketCreator.showPetLevelUp(c.getPlayer(), index));
}
IItem item = player.getInventory(MapleInventoryType.CASH).getItem(pet.getPosition());
c.announce(MaplePacketCreator.updateSlot(item));
player.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.commandResponse(player.getId(), i, 1, true), true);
remove(c, itemId);
break;
}
} else {
break;
}
}
c.announce(MaplePacketCreator.enableActions());
} else if (itemType == 530) {
ii.getItemEffect(itemId).applyTo(player);
remove(c, itemId);
} else if (itemType == 533) {
NPCScriptManager.getInstance().start(c, 9010009, null, null);
} else if (itemType == 537) {
player.setChalkboard(slea.readMapleAsciiString());
player.getMap().broadcastMessage(MaplePacketCreator.useChalkboard(player, false));
player.getClient().announce(MaplePacketCreator.enableActions());
} else if (itemType == 539) {
List<String> lines = new LinkedList<String>();
for (int i = 0; i < 4; i++) {
lines.add(slea.readMapleAsciiString());
}
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.getAvatarMega(c.getPlayer(), medal, c.getChannel(), itemId, lines, (slea.readByte() != 0)));
remove(c, itemId);
} else if (itemType == 545) { // MiuMiu's travel store
if (player.getShop() == null) {
MapleShop shop = MapleShopFactory.getInstance().getShop(1338);
if (shop != null) {
shop.sendShop(c);
remove(c, itemId);
}
} else {
c.announce(MaplePacketCreator.enableActions());
}
} else if (itemType == 550) { // Extend item expiration
c.announce(MaplePacketCreator.enableActions());
} else if (itemType == 552) {
MapleInventoryType type = MapleInventoryType.getByType((byte) slea.readInt());
byte slot = (byte) slea.readInt();
IItem item = c.getPlayer().getInventory(type).getItem(slot);
if (item == null || item.getQuantity() <= 0 || (item.getFlag() & ItemConstants.KARMA) > 0 && ii.isKarmaAble(item.getItemId())) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (type.equals(MapleInventoryType.USE)) {
item.setFlag((byte) ItemConstants.SPIKES);
} else {
item.setFlag((byte) ItemConstants.KARMA);
}
c.getPlayer().forceUpdateItem(type, item);
remove(c, itemId);
c.announce(MaplePacketCreator.enableActions());
} else if (itemType == 552) { // DS EGG THING
c.announce(MaplePacketCreator.enableActions());
} else if (itemType == 557) {
slea.readInt();
int itemSlot = slea.readInt();
slea.readInt();
final IEquip equip = (IEquip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((byte) itemSlot);
if (equip.getVicious() == 2 || c.getPlayer().getInventory(MapleInventoryType.CASH).findById(5570000) == null) {
return;
}
equip.setVicious(equip.getVicious() + 1);
equip.setUpgradeSlots(equip.getUpgradeSlots() + 1);
remove(c, itemId);
c.announce(MaplePacketCreator.enableActions());
c.announce(MaplePacketCreator.sendHammerData(equip.getVicious()));
c.announce(MaplePacketCreator.hammerItem(equip));
} else if (itemType == 561) { // VEGA'S SPELL
c.announce(MaplePacketCreator.enableActions());
} else {
Output.print("NEW CASH ITEM: " + itemType + "\n" + slea.toString());
c.announce(MaplePacketCreator.enableActions());
}
}
private static void remove(MapleClient c, int itemId) {
MapleInventoryManipulator.removeById(c, MapleInventoryType.CASH, itemId, 1, true, false);
}
private static boolean getIncubatedItem(MapleClient c, int id) {
final int[] ids = {1012070, 1302049, 1302063, 1322027, 2000004, 2000005, 2020013, 2020015, 2040307, 2040509, 2040519, 2040521, 2040533, 2040715, 2040717, 2040810, 2040811, 2070005, 2070006, 4020009,};
final int[] quantitys = {1, 1, 1, 1, 240, 200, 200, 200, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3};
int amount = 0;
for (int i = 0; i < ids.length; i++) {
if (i == id) {
amount = quantitys[i];
}
}
if (c.getPlayer().getInventory(MapleInventoryType.getByType((byte) (id / 1000000))).isFull()) {
return false;
}
MapleInventoryManipulator.addById(c, id, (short) amount);
return true;
}
}