/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 version 3
as published by the Free Software Foundation. You may not use, modify
or distribute this program under any other version of the
GNU Affero General Public License.
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 handling.channel.handler;
import client.MapleCharacter;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import client.inventory.Item;
import client.inventory.Equip;
import client.SkillFactory;
import client.MapleClient;
import client.MapleQuestStatus;
import client.MapleTrait.MapleTraitType;
import client.PlayerStats;
import client.Skill;
import client.SkillEntry;
import client.SkillFactory.CraftingEntry;
import client.inventory.ItemFlag;
import client.inventory.MapleImp;
import client.inventory.MapleImp.ImpFlag;
import client.inventory.MapleInventoryType;
import constants.GameConstants;
import java.util.HashMap;
import java.util.Map.Entry;
import server.ItemMakerFactory;
import server.ItemMakerFactory.GemCreateEntry;
import server.ItemMakerFactory.ItemMakerCreateEntry;
import server.Randomizer;
import server.MapleItemInformationProvider;
import server.MapleInventoryManipulator;
import server.MapleStatEffect;
import server.maps.MapleExtractor;
import server.maps.MapleReactor;
import server.quest.MapleQuest;
import tools.FileoutputUtil;
import tools.Pair;
import tools.packet.CField;
import tools.Triple;
import tools.data.LittleEndianAccessor;
import tools.packet.CField.EffectPacket;
import tools.packet.CWvsContext;
import tools.packet.CWvsContext.InventoryPacket;
public class ItemMakerHandler {
private static final Map<String, Integer> craftingEffects = new HashMap<>();
static {
craftingEffects.put("Effect/BasicEff.img/professions/herbalism", 92000000);
craftingEffects.put("Effect/BasicEff.img/professions/mining", 92010000);
craftingEffects.put("Effect/BasicEff.img/professions/herbalismExtract", 92000000);
craftingEffects.put("Effect/BasicEff.img/professions/miningExtract", 92010000);
craftingEffects.put("Effect/BasicEff.img/professions/equip_product", 92020000);
craftingEffects.put("Effect/BasicEff.img/professions/acc_product", 92030000);
craftingEffects.put("Effect/BasicEff.img/professions/alchemy", 92040000);
}
public static enum CraftRanking {
SOSO(19, 30),
GOOD(20, 40),
COOL(21, 50);
public int i, craft;
private CraftRanking(int i, int craft) {
this.i = i;
this.craft = craft;
}
}
public static final void ItemMaker(final LittleEndianAccessor slea, final MapleClient c) {
//System.out.println(slea.toString()); //change?
final int makerType = slea.readInt();
switch (makerType) {
case 1: { // Gem
final int toCreate = slea.readInt();
if (GameConstants.isGem(toCreate)) {
final GemCreateEntry gem = ItemMakerFactory.getInstance().getGemInfo(toCreate);
if (gem == null) {
return;
}
if (!hasSkill(c, gem.getReqSkillLevel())) {
return; // H4x
}
if (c.getPlayer().getMeso() < gem.getCost()) {
return; // H4x
}
final int randGemGiven = getRandomGem(gem.getRandomReward());
if (c.getPlayer().getInventory(GameConstants.getInventoryType(randGemGiven)).isFull()) {
return; // We'll do handling for this later
}
final int taken = checkRequiredNRemove(c, gem.getReqRecipes());
if (taken == 0) {
return; // We'll do handling for this later
}
c.getPlayer().gainMeso(-gem.getCost(), false);
MapleInventoryManipulator.addById(c, randGemGiven, (byte) (taken == randGemGiven ? 9 : 1), "Made by Gem " + toCreate + " on " + FileoutputUtil.CurrentReadable_Date()); // Gem is always 1
c.getSession().write(EffectPacket.ItemMaker_Success());
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), EffectPacket.ItemMaker_Success_3rdParty(c.getPlayer().getId()), false);
} else if (GameConstants.isOtherGem(toCreate)) {
//non-gems that are gems
//stim and numEnchanter always 0
final GemCreateEntry gem = ItemMakerFactory.getInstance().getGemInfo(toCreate);
if (gem == null) {
return;
}
if (!hasSkill(c, gem.getReqSkillLevel())) {
return; // H4x
}
if (c.getPlayer().getMeso() < gem.getCost()) {
return; // H4x
}
if (c.getPlayer().getInventory(GameConstants.getInventoryType(toCreate)).isFull()) {
return; // We'll do handling for this later
}
if (checkRequiredNRemove(c, gem.getReqRecipes()) == 0) {
return; // We'll do handling for this later
}
c.getPlayer().gainMeso(-gem.getCost(), false);
if (GameConstants.getInventoryType(toCreate) == MapleInventoryType.EQUIP) {
MapleInventoryManipulator.addbyItem(c, MapleItemInformationProvider.getInstance().getEquipById(toCreate));
} else {
MapleInventoryManipulator.addById(c, toCreate, (byte) 1, "Made by Gem " + toCreate + " on " + FileoutputUtil.CurrentReadable_Date()); // Gem is always 1
}
c.getSession().write(EffectPacket.ItemMaker_Success());
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), EffectPacket.ItemMaker_Success_3rdParty(c.getPlayer().getId()), false);
} else {
final boolean stimulator = slea.readByte() > 0;
final int numEnchanter = slea.readInt();
final ItemMakerCreateEntry create = ItemMakerFactory.getInstance().getCreateInfo(toCreate);
if (create == null) {
return;
}
if (numEnchanter > create.getTUC()) {
return; // h4x
}
if (!hasSkill(c, create.getReqSkillLevel())) {
return; // H4x
}
if (c.getPlayer().getMeso() < create.getCost()) {
return; // H4x
}
if (c.getPlayer().getInventory(GameConstants.getInventoryType(toCreate)).isFull()) {
return; // We'll do handling for this later
}
if (checkRequiredNRemove(c, create.getReqItems()) == 0) {
return; // We'll do handling for this later
}
c.getPlayer().gainMeso(-create.getCost(), false);
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
final Equip toGive = (Equip) ii.getEquipById(toCreate);
if (stimulator || numEnchanter > 0) {
if (c.getPlayer().haveItem(create.getStimulator(), 1, false, true)) {
ii.randomizeStats_Above(toGive);
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, create.getStimulator(), 1, false, false);
}
for (int i = 0; i < numEnchanter; i++) {
final int enchant = slea.readInt();
if (c.getPlayer().haveItem(enchant, 1, false, true)) {
final Map<String, Integer> stats = ii.getEquipStats(enchant);
if (stats != null) {
addEnchantStats(stats, toGive);
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, enchant, 1, false, false);
}
}
}
}
if (!stimulator || Randomizer.nextInt(10) != 0) {
MapleInventoryManipulator.addbyItem(c, toGive);
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), EffectPacket.ItemMaker_Success_3rdParty(c.getPlayer().getId()), false);
} else {
c.getPlayer().dropMessage(5, "The item was overwhelmed by the stimulator.");
}
c.getSession().write(EffectPacket.ItemMaker_Success());
}
break;
}
case 3: { // Making Crystals
final int etc = slea.readInt();
if (c.getPlayer().haveItem(etc, 100, false, true)) {
MapleInventoryManipulator.addById(c, getCreateCrystal(etc), (short) 1, "Made by Maker " + etc + " on " + FileoutputUtil.CurrentReadable_Date());
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, etc, 100, false, false);
c.getSession().write(EffectPacket.ItemMaker_Success());
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), EffectPacket.ItemMaker_Success_3rdParty(c.getPlayer().getId()), false);
}
break;
}
case 4: { // Disassembling EQ.
final int itemId = slea.readInt();
c.getPlayer().updateTick(slea.readInt());
final byte slot = (byte) slea.readInt();
final Item toUse = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(slot);
if (toUse == null || toUse.getItemId() != itemId || toUse.getQuantity() < 1) {
return;
}
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if (!ii.isDropRestricted(itemId) && !ii.isAccountShared(itemId)) {
final int[] toGive = getCrystal(itemId, ii.getReqLevel(itemId));
MapleInventoryManipulator.addById(c, toGive[0], (byte) toGive[1], "Made by disassemble " + itemId + " on " + FileoutputUtil.CurrentReadable_Date());
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, slot, (byte) 1, false);
}
c.getSession().write(EffectPacket.ItemMaker_Success());
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), EffectPacket.ItemMaker_Success_3rdParty(c.getPlayer().getId()), false);
break;
}
}
}
private static int getCreateCrystal(final int etc) {
int itemid;
final short level = MapleItemInformationProvider.getInstance().getItemMakeLevel(etc);
if (level >= 31 && level <= 50) {
itemid = 4260000;
} else if (level >= 51 && level <= 60) {
itemid = 4260001;
} else if (level >= 61 && level <= 70) {
itemid = 4260002;
} else if (level >= 71 && level <= 80) {
itemid = 4260003;
} else if (level >= 81 && level <= 90) {
itemid = 4260004;
} else if (level >= 91 && level <= 100) {
itemid = 4260005;
} else if (level >= 101 && level <= 110) {
itemid = 4260006;
} else if (level >= 111 && level <= 120) {
itemid = 4260007;
} else if (level >= 121) {
itemid = 4260008;
} else {
throw new RuntimeException("Invalid Item Maker id");
}
return itemid;
}
private static int[] getCrystal(final int itemid, final int level) {
int[] all = new int[2];
all[0] = -1;
if (level >= 31 && level <= 50) {
all[0] = 4260000;
} else if (level >= 51 && level <= 60) {
all[0] = 4260001;
} else if (level >= 61 && level <= 70) {
all[0] = 4260002;
} else if (level >= 71 && level <= 80) {
all[0] = 4260003;
} else if (level >= 81 && level <= 90) {
all[0] = 4260004;
} else if (level >= 91 && level <= 100) {
all[0] = 4260005;
} else if (level >= 101 && level <= 110) {
all[0] = 4260006;
} else if (level >= 111 && level <= 120) {
all[0] = 4260007;
} else if (level >= 121 && level <= 200) {
all[0] = 4260008;
} else {
throw new RuntimeException("Invalid Item Maker type" + level);
}
if (GameConstants.isWeapon(itemid) || GameConstants.isOverall(itemid)) {
all[1] = Randomizer.rand(5, 11);
} else {
all[1] = Randomizer.rand(3, 7);
}
return all;
}
private static void addEnchantStats(final Map<String, Integer> stats, final Equip item) {
Integer s = stats.get("PAD");
if (s != null && s != 0) {
item.setWatk((short) (item.getWatk() + s));
}
s = stats.get("MAD");
if (s != null && s != 0) {
item.setMatk((short) (item.getMatk() + s));
}
s = stats.get("ACC");
if (s != null && s != 0) {
item.setAcc((short) (item.getAcc() + s));
}
s = stats.get("EVA");
if (s != null && s != 0) {
item.setAvoid((short) (item.getAvoid() + s));
}
s = stats.get("Speed");
if (s != null && s != 0) {
item.setSpeed((short) (item.getSpeed() + s));
}
s = stats.get("Jump");
if (s != null && s != 0) {
item.setJump((short) (item.getJump() + s));
}
s = stats.get("MaxHP");
if (s != null && s != 0) {
item.setHp((short) (item.getHp() + s));
}
s = stats.get("MaxMP");
if (s != null && s != 0) {
item.setMp((short) (item.getMp() + s));
}
s = stats.get("STR");
if (s != null && s != 0) {
item.setStr((short) (item.getStr() + s));
}
s = stats.get("DEX");
if (s != null && s != 0) {
item.setDex((short) (item.getDex() + s));
}
s = stats.get("INT");
if (s != null && s != 0) {
item.setInt((short) (item.getInt() + s));
}
s = stats.get("LUK");
if (s != null && s != 0) {
item.setLuk((short) (item.getLuk() + s));
}
s = stats.get("randOption");
if (s != null && s != 0) {
final int ma = item.getMatk(), wa = item.getWatk();
if (wa > 0) {
item.setWatk((short) (Randomizer.nextBoolean() ? (wa + s) : (wa - s)));
}
if (ma > 0) {
item.setMatk((short) (Randomizer.nextBoolean() ? (ma + s) : (ma - s)));
}
}
s = stats.get("randStat");
if (s != null && s != 0) {
final int str = item.getStr(), dex = item.getDex(), luk = item.getLuk(), int_ = item.getInt();
if (str > 0) {
item.setStr((short) (Randomizer.nextBoolean() ? (str + s) : (str - s)));
}
if (dex > 0) {
item.setDex((short) (Randomizer.nextBoolean() ? (dex + s) : (dex - s)));
}
if (int_ > 0) {
item.setInt((short) (Randomizer.nextBoolean() ? (int_ + s) : (int_ - s)));
}
if (luk > 0) {
item.setLuk((short) (Randomizer.nextBoolean() ? (luk + s) : (luk - s)));
}
}
}
private static int getRandomGem(final List<Pair<Integer, Integer>> rewards) {
int itemid;
final List<Integer> items = new ArrayList<>();
for (final Pair p : rewards) {
itemid = (Integer) p.getLeft();
for (int i = 0; i < (Integer) p.getRight(); i++) {
items.add(itemid);
}
}
return items.get(Randomizer.nextInt(items.size()));
}
private static int checkRequiredNRemove(final MapleClient c, final List<Pair<Integer, Integer>> recipe) {
int itemid = 0;
for (final Pair<Integer, Integer> p : recipe) {
if (!c.getPlayer().haveItem(p.getLeft(), p.getRight(), false, true)) {
return 0;
}
}
for (final Pair<Integer, Integer> p : recipe) {
itemid = p.getLeft();
MapleInventoryManipulator.removeById(c, GameConstants.getInventoryType(itemid), itemid, p.getRight(), false, false);
}
return itemid;
}
private static boolean hasSkill(final MapleClient c, final int reqlvl) {
return c.getPlayer().getSkillLevel(SkillFactory.getSkill(PlayerStats.getSkillByJob(1007, c.getPlayer().getJob()))) >= reqlvl;
}
public static final void UseRecipe(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
if (chr == null || !chr.isAlive() || chr.getMap() == null || chr.hasBlockedInventory()) {
c.getSession().write(CWvsContext.enableActions());
return;
}
c.getPlayer().updateTick(slea.readInt());
final byte slot = (byte) slea.readShort();
final int itemId = slea.readInt();
final Item toUse = chr.getInventory(MapleInventoryType.USE).getItem(slot);
if (toUse == null || toUse.getQuantity() < 1 || toUse.getItemId() != itemId || itemId / 10000 != 251) {
c.getSession().write(CWvsContext.enableActions());
return;
}
if (MapleItemInformationProvider.getInstance().getItemEffect(toUse.getItemId()).applyTo(chr)) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, slot, (short) 1, false);
}
}
public static final void MakeExtractor(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
if (chr == null || !chr.isAlive() || chr.getMap() == null || chr.hasBlockedInventory()) {
c.getSession().write(CWvsContext.enableActions());
return;
}
final int itemId = slea.readInt();
final int fee = slea.readInt();
final Item toUse = chr.getInventory(MapleInventoryType.SETUP).findById(itemId);
if (toUse == null || toUse.getQuantity() < 1 || itemId / 10000 != 304 || fee <= 0 || chr.getExtractor() != null || !chr.getMap().isTown()) {
c.getSession().write(CWvsContext.enableActions());
return;
}
chr.setExtractor(new MapleExtractor(chr, itemId, fee, chr.getFH())); //no clue about time left
chr.getMap().spawnExtractor(chr.getExtractor());
//expiry date ..
//MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.SETUP, toUse.getPosition(), (short) 1, false);
}
public static final void UseBag(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
if (chr == null || !chr.isAlive() || chr.getMap() == null || chr.hasBlockedInventory()) {
c.getSession().write(CWvsContext.enableActions());
return;
}
c.getPlayer().updateTick(slea.readInt());
final byte slot = (byte) slea.readShort();
final int itemId = slea.readInt();
final Item toUse = chr.getInventory(MapleInventoryType.ETC).getItem(slot);
if (toUse == null || toUse.getQuantity() < 1 || toUse.getItemId() != itemId || itemId / 10000 != 433) {
c.getSession().write(CWvsContext.enableActions());
return;
}
boolean firstTime = !chr.getExtendedSlots().contains(itemId);
if (firstTime) {
chr.getExtendedSlots().add(itemId);
chr.changedExtended();
short flag = toUse.getFlag();
flag |= ItemFlag.LOCK.getValue();
flag |= ItemFlag.UNTRADABLE.getValue();
toUse.setFlag(flag);
c.getSession().write(InventoryPacket.updateSpecialItemUse(toUse, (byte) 4, toUse.getPosition(), true, chr));
}
c.getSession().write(CField.openBag(chr.getExtendedSlots().indexOf(itemId), itemId, firstTime));
c.getSession().write(CWvsContext.enableActions());
}
public static final void StartHarvest(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
//its ok if a hacker bypasses this as we do everything in the reactor anyway
final MapleReactor reactor = c.getPlayer().getMap().getReactorByOid(slea.readInt());
if (reactor == null || !reactor.isAlive() || reactor.getReactorId() > 200011 || chr.getStat().harvestingTool <= 0 || reactor.getTruePosition().distanceSq(chr.getTruePosition()) > 10000 || c.getPlayer().getFatigue() >= 200) {
return;
}
Item item = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) c.getPlayer().getStat().harvestingTool);
if (item == null || ((Equip) item).getDurability() == 0) {
c.getPlayer().getStat().handleProfessionTool(c.getPlayer());
return;
}
MapleQuestStatus marr = c.getPlayer().getQuestNAdd(MapleQuest.getInstance(GameConstants.HARVEST_TIME));
if (marr.getCustomData() == null) {
marr.setCustomData("0");
}
long lastTime = Long.parseLong(marr.getCustomData());
if (lastTime + (5000) > System.currentTimeMillis()) {
c.getPlayer().dropMessage(5, "You may not harvest yet.");
} else {
marr.setCustomData(String.valueOf(System.currentTimeMillis()));
c.getSession().write(CField.harvestMessage(reactor.getObjectId(), 13)); //ok to harvest, gogo
c.getPlayer().getMap().broadcastMessage(chr, CField.showHarvesting(chr.getId(), item.getItemId()), false);
}
}
public static final void StopHarvest(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
//its ok if a hacker bypasses this as we do everything in the reactor anyway
/*final MapleReactor reactor = c.getPlayer().getMap().getReactorByOid(slea.readInt());
if (reactor == null || !reactor.isAlive() || reactor.getReactorId() > 200011 || chr.getStats().harvestingTool <= 0 || reactor.getTruePosition().distanceSq(chr.getTruePosition()) > 40000.0 || reactor.getState() < 3 || c.getPlayer().getFatigue() >= 100) { //bug in global, so we use this to bug fix
return;
}
Item item = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) c.getPlayer().getStats().harvestingTool);
if (item == null || ((Equip) item).getDurability() == 0) {
c.getPlayer().getStats().handleProfessionTool(c.getPlayer());
return;
}
c.getPlayer().getMap().destroyReactor(reactor.getObjectId());
ReactorScriptManager.getInstance().act(c, reactor);*/
}
public static void ProfessionInfo(final LittleEndianAccessor slea, final MapleClient c) { //so pointless
try {
String skillid = slea.readMapleAsciiString();
int level1 = slea.readInt();
int level2 = slea.readInt();
int rate;
if (skillid.startsWith("9200") || skillid.startsWith("9201")) {
rate = 100;
} else if (skillid.equals("honorLeveling")) {
c.getSession().write(CWvsContext.updateSpecialStat(skillid, level1, level2, c.getPlayer().getHonourNextExp()));
return;
} else if (skillid.equals("hyper")) {
c.getSession().write(CWvsContext.updateSpecialStat(skillid, level1, level2, 0));
return;
} else {
rate = Math.max(0, 100 - ((level1 + 1) - c.getPlayer().getProfessionLevel(Integer.parseInt(skillid))) * 20);
}
c.getSession().write(CWvsContext.updateSpecialStat(skillid, level1, level2, rate));
} catch (NumberFormatException nfe) {
}
}
public static final void CraftEffect(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
if (chr.getMapId() != 910001000 && chr.getMap().getExtractorSize() <= 0) {
return; //ardent mill
}
final String effect = slea.readMapleAsciiString();
final Integer profession = craftingEffects.get(effect);
if (profession != null && (c.getPlayer().getProfessionLevel(profession.intValue()) > 0 || (profession == 92040000 && chr.getMap().getExtractorSize() > 0))) {
int time = slea.readInt();
if (time > 6000 || time < 3000) {
time = 4000;
}
c.getSession().write(EffectPacket.showOwnCraftingEffect(effect, (byte) chr.getDirection(), time, effect.endsWith("Extract") ? 1 : 0));
chr.getMap().broadcastMessage(chr, EffectPacket.showCraftingEffect(chr.getId(), effect, (byte) chr.getDirection(), time, effect.endsWith("Extract") ? 1 : 0), false);
}
}
public static final void CraftMake(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
if (chr.getMapId() != 910001000 && chr.getMap().getExtractorSize() <= 0) {
return; //ardent mill
}
final int something = slea.readInt(); //no clue what it is, but its between 288 and 305..
//if (something >= 280 && something <= 310) {
int time = slea.readInt();
if (time > 6000 || time < 3000) {
time = 4000;
}
chr.getMap().broadcastMessage(CField.craftMake(chr.getId(), something, time));
//}
}
public static final void CraftComplete(final LittleEndianAccessor slea, final MapleClient c, final MapleCharacter chr) {
final int craftID = slea.readInt();
final CraftingEntry ce = SkillFactory.getCraft(craftID);
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if ((chr.getMapId() != 910001000 && (craftID != 92049000 || chr.getMap().getExtractorSize() <= 0)) || ce == null || chr.getFatigue() >= 200) {
return;
}
final int theLevl = c.getPlayer().getProfessionLevel((craftID / 10000) * 10000);
if (theLevl <= 0 && craftID != 92049000) {
return;
}
int toGet = 0, expGain = 0, fatigue = 0;
short quantity = 1;
CraftRanking cr = CraftRanking.GOOD;
if (craftID == 92049000) { //disassembling
final int extractorId = slea.readInt();
final int itemId = slea.readInt();
final long invId = slea.readLong();
final int reqLevel = ii.getReqLevel(itemId);
final Item item = chr.getInventory(MapleInventoryType.EQUIP).findByInventoryId(invId, itemId);
if (item == null || chr.getInventory(MapleInventoryType.ETC).isFull()) {
return;
}
if (extractorId <= 0 && (theLevl == 0 || theLevl < (reqLevel > 130 ? 6 : ((reqLevel - 30) / 20)))) {
return;
} else if (extractorId > 0) {
final MapleCharacter extract = chr.getMap().getCharacterById(extractorId);
if (extract == null || extract.getExtractor() == null) {
return;
}
final MapleExtractor extractor = extract.getExtractor();
if (extractor.owner != chr.getId()) { //fee
if (chr.getMeso() < extractor.fee) {
return;
}
final MapleStatEffect eff = ii.getItemEffect(extractor.itemId);
if (eff != null && eff.getUseLevel() < reqLevel) {
return;
}
chr.gainMeso(-extractor.fee, true);
final MapleCharacter owner = chr.getMap().getCharacterById(extractor.owner);
if (owner != null && owner.getMeso() < (Integer.MAX_VALUE - extractor.fee)) {
owner.gainMeso(extractor.fee, false);
}
}
}
toGet = 4031016;
quantity = (short) Randomizer.rand(3, GameConstants.isWeapon(itemId) || GameConstants.isOverall(itemId) ? 11 : 7);
if (reqLevel <= 60) {
toGet = 4021013;
} else if (reqLevel <= 90) {
toGet = 4021014;
} else if (reqLevel <= 120) {
toGet = 4021015;
}
if (quantity <= 5) {
cr = CraftRanking.SOSO;
}
if (Randomizer.nextInt(5) == 0 && toGet != 4031016) {
toGet++;
quantity = 1;
cr = CraftRanking.COOL;
}
fatigue = 3;
MapleInventoryManipulator.addById(c, toGet, quantity, "Made by disassemble " + itemId + " on " + FileoutputUtil.CurrentReadable_Date());
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, item.getPosition(), (byte) 1, false);
} else if (craftID == 92049001) { //fusing.
final int itemId = slea.readInt();
final long invId1 = slea.readLong();
final long invId2 = slea.readLong();
final int reqLevel = ii.getReqLevel(itemId);
Equip item1 = (Equip) chr.getInventory(MapleInventoryType.EQUIP).findByInventoryIdOnly(invId1, itemId);
Equip item2 = (Equip) chr.getInventory(MapleInventoryType.EQUIP).findByInventoryIdOnly(invId2, itemId);
for (short i = 0; i < chr.getInventory(MapleInventoryType.EQUIP).getSlotLimit(); i++) {
Item item = chr.getInventory(MapleInventoryType.EQUIP).getItem(i);
if (item != null && item.getItemId() == itemId && item != item1 && item != item2) {
if (item1 == null) {
item1 = (Equip) item;
} else if (item2 == null) {
item2 = (Equip) item;
break;
}
}
}
if (item1 == null || item2 == null) {
return;
}
if (theLevl < (reqLevel > 130 ? 6 : ((reqLevel - 30) / 20))) {
return;
}
int potentialState = 17, potentialChance = (theLevl * 2);
if (item1.getState() > 0 && item2.getState() > 0) {
potentialChance = 100;
} else if (item1.getState() > 0 || item2.getState() > 0) {
potentialChance *= 2;
}
if (item1.getState() == item2.getState() && item1.getState() > 17) {
potentialState = item1.getState();
}
//use average stats if scrolled.
Equip newEquip = ii.fuse(item1.getLevel() > 0 ? (Equip) ii.getEquipById(itemId) : item1, item2.getLevel() > 0 ? (Equip) ii.getEquipById(itemId) : item2);
final int newStat = ii.getTotalStat(newEquip);
if (newStat > ii.getTotalStat(item1) || newStat > ii.getTotalStat(item2)) {
cr = CraftRanking.COOL;
} else if (newStat < ii.getTotalStat(item1) || newStat < ii.getTotalStat(item2)) {
cr = CraftRanking.SOSO;
}
if (Randomizer.nextInt(100) < (newEquip.getUpgradeSlots() > 0 || potentialChance >= 100 ? potentialChance : (potentialChance / 2))) {
newEquip.resetPotential_Fuse(theLevl > 5, potentialState);
}
newEquip.setFlag((short) ItemFlag.CRAFTED.getValue());
newEquip.setOwner(chr.getName());
toGet = newEquip.getItemId();
expGain = (60 - ((theLevl - 1) * 2)) * 2;
fatigue = 3;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, item1.getPosition(), (byte) 1, false);
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, item2.getPosition(), (byte) 1, false);
MapleInventoryManipulator.addbyItem(c, newEquip);
} else {
if (ce.needOpenItem && chr.getSkillLevel(craftID) <= 0) {
return;
}
for (Entry<Integer, Integer> e : ce.reqItems.entrySet()) {
if (!chr.haveItem(e.getKey(), e.getValue())) {
return;
}
}
for (Triple<Integer, Integer, Integer> i : ce.targetItems) {
if (!MapleInventoryManipulator.checkSpace(c, i.left, i.mid, "")) {
return;
}
}
for (Entry<Integer, Integer> e : ce.reqItems.entrySet()) {
MapleInventoryManipulator.removeById(c, GameConstants.getInventoryType(e.getKey()), e.getKey(), e.getValue(), false, false);
}
if (Randomizer.nextInt(100) < (100 - (ce.reqSkillLevel - theLevl) * 20) || (craftID / 10000 <= 9201)) {
final Map<Skill, SkillEntry> sa = new HashMap<>();
while (true) {
boolean passed = false;
for (Triple<Integer, Integer, Integer> i : ce.targetItems) {
if (Randomizer.nextInt(100) < i.right) {
toGet = i.left;
quantity = i.mid.shortValue();
Item receive;
if (GameConstants.getInventoryType(toGet) == MapleInventoryType.EQUIP) {
Equip first = (Equip) ii.getEquipById(toGet);
if (Randomizer.nextInt(100) < (theLevl * 2)) {
first = (Equip) ii.randomizeStats(first);
cr = CraftRanking.COOL;
}
if (Randomizer.nextInt(100) < (theLevl * (first.getUpgradeSlots() > 0 ? 2 : 1))) {
first.resetPotential();
cr = CraftRanking.COOL;
}
receive = first;
receive.setFlag((short) ItemFlag.CRAFTED.getValue());
} else {
receive = new Item(toGet, (short) 0, quantity, (short) (ItemFlag.CRAFTED_USE.getValue()));
}
if (ce.period > 0) {
receive.setExpiration(System.currentTimeMillis() + (ce.period * 60000)); //period is in minutes
}
receive.setOwner(chr.getName());
receive.setGMLog("Crafted from " + craftID + " on " + FileoutputUtil.CurrentReadable_Date());
MapleInventoryManipulator.addFromDrop(c, receive, true, false);
if (ce.needOpenItem) {
byte mLevel = chr.getMasterLevel(craftID);
if (mLevel == 1) {
sa.put(ce, new SkillEntry(0, (byte) 0, SkillFactory.getDefaultSExpiry(ce)));
} else if (mLevel > 1) {
sa.put(ce, new SkillEntry(Integer.MAX_VALUE, (byte) (chr.getMasterLevel(craftID) - 1), SkillFactory.getDefaultSExpiry(ce)));
}
}
fatigue = ce.incFatigability;
expGain = ce.incSkillProficiency == 0 ? (((fatigue * 20) - (ce.reqSkillLevel - theLevl) * 2) * 2) : ce.incSkillProficiency;
chr.getTrait(MapleTraitType.craft).addExp(cr.craft, chr);
passed = true;
break;
}
}
if (passed) {
break;
}
}
chr.changeSkillsLevel(sa);
} else {
quantity = 0;
cr = CraftRanking.SOSO;
}
}
if (expGain > 0 && theLevl < 10) {
expGain *= chr.getClient().getChannelServer().getTraitRate();
if (Randomizer.nextInt(100) < chr.getTrait(MapleTraitType.craft).getLevel() / 5) {
expGain *= 2;
}
String s = "Alchemy";
switch (craftID / 10000) {
case 9200:
s = "Herbalism";
break;
case 9201:
s = "Mining";
break;
case 9202:
s = "Smithing";
break;
case 9203:
s = "Accessory Crafting";
break;
}
chr.dropMessage(-5, s + "'s mastery increased. (+" + expGain + ")");
if (chr.addProfessionExp((craftID / 10000) * 10000, expGain)) {
chr.dropMessage(1, "You've accumulated " + s + " mastery. See an NPC in town to level up.");
}
} else {
expGain = 0;
}
MapleQuest.getInstance(2550).forceStart(c.getPlayer(), 9031000, "1"); //removes tutorial stuff
chr.setFatigue((byte) (chr.getFatigue() + fatigue));
chr.getMap().broadcastMessage(CField.craftFinished(chr.getId(), craftID, cr.i, toGet, quantity, expGain));
}
public static final void UsePot(final LittleEndianAccessor slea, final MapleClient c) {
final int itemid = slea.readInt();
final Item slot = c.getPlayer().getInventory(MapleInventoryType.USE).getItem(slea.readShort());
if (slot == null || slot.getQuantity() <= 0 || slot.getItemId() != itemid || itemid / 10000 != 244 || MapleItemInformationProvider.getInstance().getPot(itemid) == null) {
c.getSession().write(CWvsContext.enableActions());
return;
}
c.getSession().write(CWvsContext.enableActions());
for (int i = 0; i < c.getPlayer().getImps().length; i++) {
if (c.getPlayer().getImps()[i] == null) {
c.getPlayer().getImps()[i] = new MapleImp(itemid);
c.getSession().write(CWvsContext.updateImp(c.getPlayer().getImps()[i], ImpFlag.SUMMONED.getValue(), i, false));
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, slot.getPosition(), (short) 1, false, false);
return;
}
}
}
public static final void ClearPot(final LittleEndianAccessor slea, final MapleClient c) {
final int index = slea.readInt() - 1;
if (index < 0 || index >= c.getPlayer().getImps().length || c.getPlayer().getImps()[index] == null) {
c.getSession().write(CWvsContext.enableActions());
return;
}
c.getSession().write(CWvsContext.updateImp(c.getPlayer().getImps()[index], ImpFlag.REMOVED.getValue(), index, false));
c.getPlayer().getImps()[index] = null;
}
public static final void FeedPot(final LittleEndianAccessor slea, final MapleClient c) {
final int itemid = slea.readInt();
final Item slot = c.getPlayer().getInventory(GameConstants.getInventoryType(itemid)).getItem((short) slea.readInt());
if (slot == null || slot.getQuantity() <= 0 || slot.getItemId() != itemid) {
c.getSession().write(CWvsContext.enableActions());
return;
}
final int level = GameConstants.getInventoryType(itemid) == MapleInventoryType.ETC ? MapleItemInformationProvider.getInstance().getItemMakeLevel(itemid) : MapleItemInformationProvider.getInstance().getReqLevel(itemid);
if (level <= 0 || level < (Math.min(120, c.getPlayer().getLevel()) - 50) || (GameConstants.getInventoryType(itemid) != MapleInventoryType.ETC && GameConstants.getInventoryType(itemid) != MapleInventoryType.EQUIP)) {
c.getPlayer().dropMessage(1, "The item must be within 50 levels of you.");
c.getSession().write(CWvsContext.enableActions());
return;
}
final int index = slea.readInt() - 1;
if (index < 0 || index >= c.getPlayer().getImps().length || c.getPlayer().getImps()[index] == null || c.getPlayer().getImps()[index].getLevel() >= (MapleItemInformationProvider.getInstance().getPot(c.getPlayer().getImps()[index].getItemId()).right - 1) || c.getPlayer().getImps()[index].getState() != 1) {
c.getSession().write(CWvsContext.enableActions());
return;
}
int mask = ImpFlag.FULLNESS.getValue();
mask |= ImpFlag.FULLNESS_2.getValue();
mask |= ImpFlag.UPDATE_TIME.getValue();
mask |= ImpFlag.AWAKE_TIME.getValue();
//this is where the magic happens
c.getPlayer().getImps()[index].setFullness(c.getPlayer().getImps()[index].getFullness() + (100 * (GameConstants.getInventoryType(itemid) == MapleInventoryType.EQUIP ? 2 : 1)));
if (Randomizer.nextBoolean()) {
mask |= ImpFlag.CLOSENESS.getValue();
c.getPlayer().getImps()[index].setCloseness(c.getPlayer().getImps()[index].getCloseness() + 1 + (Randomizer.nextInt(5 * (GameConstants.getInventoryType(itemid) == MapleInventoryType.EQUIP ? 2 : 1))));
} else if (Randomizer.nextInt(5) == 0) { //1/10 chance of sickness
c.getPlayer().getImps()[index].setState(4); //sick
mask |= ImpFlag.STATE.getValue();
}
if (c.getPlayer().getImps()[index].getFullness() >= 1000) {
c.getPlayer().getImps()[index].setState(1);
c.getPlayer().getImps()[index].setFullness(0);
c.getPlayer().getImps()[index].setLevel(c.getPlayer().getImps()[index].getLevel() + 1);
mask |= ImpFlag.SUMMONED.getValue();
if (c.getPlayer().getImps()[index].getLevel() >= (MapleItemInformationProvider.getInstance().getPot(c.getPlayer().getImps()[index].getItemId()).right - 1)) {
c.getPlayer().getImps()[index].setState(5);
}
}
MapleInventoryManipulator.removeFromSlot(c, GameConstants.getInventoryType(itemid), slot.getPosition(), (short) 1, false, false);
c.getSession().write(CWvsContext.updateImp(c.getPlayer().getImps()[index], mask, index, false));
}
public static final void CurePot(final LittleEndianAccessor slea, final MapleClient c) {
final int itemid = slea.readInt();
final Item slot = c.getPlayer().getInventory(MapleInventoryType.ETC).getItem((short) slea.readInt());
if (slot == null || slot.getQuantity() <= 0 || slot.getItemId() != itemid || itemid / 10000 != 434) {
c.getSession().write(CWvsContext.enableActions());
return;
}
final int index = slea.readInt() - 1;
if (index < 0 || index >= c.getPlayer().getImps().length || c.getPlayer().getImps()[index] == null || c.getPlayer().getImps()[index].getState() != 4) {
c.getSession().write(CWvsContext.enableActions());
return;
}
c.getPlayer().getImps()[index].setState(1);
c.getSession().write(CWvsContext.updateImp(c.getPlayer().getImps()[index], ImpFlag.STATE.getValue(), index, false));
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.ETC, slot.getPosition(), (short) 1, false, false);
}
public static final void RewardPot(final LittleEndianAccessor slea, final MapleClient c) {
final int index = slea.readInt() - 1;
if (index < 0 || index >= c.getPlayer().getImps().length || c.getPlayer().getImps()[index] == null || c.getPlayer().getImps()[index].getLevel() < (MapleItemInformationProvider.getInstance().getPot(c.getPlayer().getImps()[index].getItemId()).right - 1)) {
c.getSession().write(CWvsContext.enableActions());
return;
}
final int itemid = GameConstants.getRewardPot(c.getPlayer().getImps()[index].getItemId(), c.getPlayer().getImps()[index].getCloseness());
if (itemid <= 0 || !MapleInventoryManipulator.checkSpace(c, itemid, (short) 1, "")) {
c.getPlayer().dropMessage(1, "Please make some space.");
c.getSession().write(CWvsContext.enableActions());
return;
}
MapleInventoryManipulator.addById(c, itemid, (short) 1, "Item Pot from " + c.getPlayer().getImps()[index].getItemId() + " on " + FileoutputUtil.CurrentReadable_Date());
c.getSession().write(CWvsContext.updateImp(c.getPlayer().getImps()[index], ImpFlag.REMOVED.getValue(), index, false));
c.getPlayer().getImps()[index] = null;
}
}