/* This file is part of the OdinMS Maple Story Server Copyright (C) 2008 Patrick Huy Matthias Butz Jan Christian Meyer 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 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 . */ package scripting; import client.Character; import client.Character.DelayedQuestUpdate; import client.*; import client.inventory.*; import client.inventory.manipulator.InventoryManipulator; import config.YamlConfig; import constants.game.GameConstants; import constants.inventory.ItemConstants; import net.server.Server; import net.server.guild.MapleGuild; import net.server.world.MapleParty; import net.server.world.MaplePartyCharacter; import scripting.event.EventInstanceManager; import scripting.event.EventManager; import scripting.npc.NPCScriptManager; import server.MapleItemInformationProvider; import server.MapleMarriage; import server.expeditions.MapleExpedition; import server.expeditions.MapleExpeditionBossLog; import server.expeditions.MapleExpeditionType; import server.life.*; import server.maps.MapleMap; import server.maps.MapleMapObject; import server.maps.MapleMapObjectType; import server.partyquest.PartyQuest; import server.partyquest.Pyramid; import server.quest.MapleQuest; import tools.PacketCreator; import tools.Pair; import java.awt.*; import java.util.List; import java.util.*; public class AbstractPlayerInteraction { public Client c; public AbstractPlayerInteraction(Client c) { this.c = c; } public Client getClient() { return c; } public Character getPlayer() { return c.getPlayer(); } public Character getChar() { return c.getPlayer(); } public int getJobId() { return getPlayer().getJob().getId(); } public Job getJob(){ return getPlayer().getJob(); } public int getLevel() { return getPlayer().getLevel(); } public MapleMap getMap() { return c.getPlayer().getMap(); } public int getHourOfDay() { return Calendar.getInstance().get(Calendar.HOUR_OF_DAY); } public int getMarketPortalId(int mapId) { return getMarketPortalId(getWarpMap(mapId)); } private int getMarketPortalId(MapleMap map) { return (map.findMarketPortal() != null) ? map.findMarketPortal().getId() : map.getRandomPlayerSpawnpoint().getId(); } public void warp(int mapid) { getPlayer().changeMap(mapid); } public void warp(int map, int portal) { getPlayer().changeMap(map, portal); } public void warp(int map, String portal) { getPlayer().changeMap(map, portal); } public void warpMap(int map) { getPlayer().getMap().warpEveryone(map); } public void warpParty(int id) { warpParty(id, 0); } public void warpParty(int id, int portalId) { int mapid = getMapId(); warpParty(id, portalId, mapid, mapid); } public void warpParty(int id, int fromMinId, int fromMaxId) { warpParty(id, 0, fromMinId, fromMaxId); } public void warpParty(int id, int portalId, int fromMinId, int fromMaxId) { for (Character mc : this.getPlayer().getPartyMembersOnline()) { if (mc.isLoggedinWorld()) { if(mc.getMapId() >= fromMinId && mc.getMapId() <= fromMaxId) { mc.changeMap(id, portalId); } } } } public MapleMap getWarpMap(int map) { return getPlayer().getWarpMap(map); } public MapleMap getMap(int map) { return getWarpMap(map); } public int countAllMonstersOnMap(int map) { return getMap(map).countMonsters(); } public int countMonster() { return getPlayer().getMap().countMonsters(); } public void resetMapObjects(int mapid) { getWarpMap(mapid).resetMapObjects(); } public EventManager getEventManager(String event) { return getClient().getEventManager(event); } public EventInstanceManager getEventInstance() { return getPlayer().getEventInstance(); } public Inventory getInventory(int type) { return getPlayer().getInventory(InventoryType.getByType((byte) type)); } public Inventory getInventory(InventoryType type) { return getPlayer().getInventory(type); } public boolean hasItem(int itemid) { return haveItem(itemid, 1); } public boolean hasItem(int itemid, int quantity) { return haveItem(itemid, quantity); } public boolean haveItem(int itemid) { return haveItem(itemid, 1); } public boolean haveItem(int itemid, int quantity) { return getPlayer().getItemQuantity(itemid, false) >= quantity; } public int getItemQuantity(int itemid) { return getPlayer().getItemQuantity(itemid, false); } public boolean haveItemWithId(int itemid) { return haveItemWithId(itemid, false); } public boolean haveItemWithId(int itemid, boolean checkEquipped) { return getPlayer().haveItemWithId(itemid, checkEquipped); } public boolean canHold(int itemid) { return canHold(itemid, 1); } public boolean canHold(int itemid, int quantity) { return canHoldAll(Collections.singletonList(itemid), Collections.singletonList(quantity), true); } public boolean canHold(int itemid, int quantity, int removeItemid, int removeQuantity) { return canHoldAllAfterRemoving(Collections.singletonList(itemid), Collections.singletonList(quantity), Collections.singletonList(removeItemid), Collections.singletonList(removeQuantity)); } private List convertToIntegerList(List objects) { List intList = new ArrayList<>(); for (Object object : objects) { intList.add((Integer) object); } return intList; } public boolean canHoldAll(List itemids) { List quantity = new LinkedList<>(); final int intOne = 1; for (int i = 0; i < itemids.size(); i++) { quantity.add(intOne); } return canHoldAll(itemids, quantity); } public boolean canHoldAll(List itemids, List quantity) { return canHoldAll(convertToIntegerList(itemids), convertToIntegerList(quantity), true); } private boolean canHoldAll(List itemids, List quantity, boolean isInteger) { int size = Math.min(itemids.size(), quantity.size()); List> addedItems = new LinkedList<>(); for(int i = 0; i < size; i++) { Item it = new Item(itemids.get(i), (short) 0, quantity.get(i).shortValue()); addedItems.add(new Pair<>(it, ItemConstants.getInventoryType(itemids.get(i)))); } return Inventory.checkSpots(c.getPlayer(), addedItems); } private List> prepareProofInventoryItems(List> items) { List> addedItems = new LinkedList<>(); for(Pair p : items) { Item it = new Item(p.getLeft(), (short) 0, p.getRight().shortValue()); addedItems.add(new Pair<>(it, InventoryType.CANHOLD)); } return addedItems; } private List>> prepareInventoryItemList(List itemids, List quantity) { int size = Math.min(itemids.size(), quantity.size()); List>> invList = new ArrayList<>(6); for(int i = InventoryType.UNDEFINED.getType(); i < InventoryType.CASH.getType(); i++) { invList.add(new LinkedList<>()); } for(int i = 0; i < size; i++) { int itemid = itemids.get(i); invList.get(ItemConstants.getInventoryType(itemid).getType()).add(new Pair<>(itemid, quantity.get(i))); } return invList; } public boolean canHoldAllAfterRemoving(List toAddItemids, List toAddQuantity, List toRemoveItemids, List toRemoveQuantity) { List>> toAddItemList = prepareInventoryItemList(toAddItemids, toAddQuantity); List>> toRemoveItemList = prepareInventoryItemList(toRemoveItemids, toRemoveQuantity); InventoryProof prfInv = (InventoryProof) this.getInventory(InventoryType.CANHOLD); prfInv.lockInventory(); try { for(int i = InventoryType.EQUIP.getType(); i < InventoryType.CASH.getType(); i++) { List> toAdd = toAddItemList.get(i); if(!toAdd.isEmpty()) { List> toRemove = toRemoveItemList.get(i); Inventory inv = this.getInventory(i); prfInv.cloneContents(inv); for(Pair p : toRemove) { InventoryManipulator.removeById(c, InventoryType.CANHOLD, p.getLeft(), p.getRight(), false, false); } List> addItems = prepareProofInventoryItems(toAdd); boolean canHold = Inventory.checkSpots(c.getPlayer(), addItems, true); if(!canHold) { return false; } } } } finally { prfInv.flushContents(); prfInv.unlockInventory(); } return true; } //---- \/ \/ \/ \/ \/ \/ \/ NOT TESTED \/ \/ \/ \/ \/ \/ \/ \/ \/ ---- public final QuestStatus getQuestRecord(final int id) { return c.getPlayer().getQuestNAdd(MapleQuest.getInstance(id)); } public final QuestStatus getQuestNoRecord(final int id) { return c.getPlayer().getQuestNoAdd(MapleQuest.getInstance(id)); } //---- /\ /\ /\ /\ /\ /\ /\ NOT TESTED /\ /\ /\ /\ /\ /\ /\ /\ /\ ---- public void openNpc(int npcid) { openNpc(npcid, null); } public void openNpc(int npcid, String script) { if (c.getCM() != null) { return; } c.removeClickedNPC(); NPCScriptManager.getInstance().dispose(c); NPCScriptManager.getInstance().start(c, npcid, script, null); } public int getQuestStatus(int id) { return c.getPlayer().getQuest(MapleQuest.getInstance(id)).getStatus().getId(); } private QuestStatus.Status getQuestStat(int id) { return c.getPlayer().getQuest(MapleQuest.getInstance(id)).getStatus(); } public boolean isQuestCompleted(int id) { try { return getQuestStat(id) == QuestStatus.Status.COMPLETED; } catch (NullPointerException e) { e.printStackTrace(); return false; } } public boolean isQuestActive(int id) { return isQuestStarted(id); } public boolean isQuestStarted(int id) { try { return getQuestStat(id) == QuestStatus.Status.STARTED; } catch (NullPointerException e) { e.printStackTrace(); return false; } } public void setQuestProgress(int id, String progress) { setQuestProgress(id, 0, progress); } public void setQuestProgress(int id, int progress) { setQuestProgress(id, 0, "" + progress); } public void setQuestProgress(int id, int infoNumber, int progress) { setQuestProgress(id, infoNumber, "" + progress); } public void setQuestProgress(int id, int infoNumber, String progress) { c.getPlayer().setQuestProgress(id, infoNumber, progress); } public String getQuestProgress(int id) { return getQuestProgress(id, 0); } public String getQuestProgress(int id, int infoNumber) { QuestStatus qs = getPlayer().getQuest(MapleQuest.getInstance(id)); if (qs.getInfoNumber() == infoNumber && infoNumber > 0) { qs = getPlayer().getQuest(MapleQuest.getInstance(infoNumber)); infoNumber = 0; } if (qs != null) { return qs.getProgress(infoNumber); } else { return ""; } } public int getQuestProgressInt(int id) { try { return Integer.parseInt(getQuestProgress(id)); } catch (NumberFormatException nfe) { return 0; } } public int getQuestProgressInt(int id, int infoNumber) { try { return Integer.parseInt(getQuestProgress(id, infoNumber)); } catch (NumberFormatException nfe) { return 0; } } public void resetAllQuestProgress(int id) { QuestStatus qs = getPlayer().getQuest(MapleQuest.getInstance(id)); if (qs != null) { qs.resetAllProgress(); getPlayer().announceUpdateQuest(DelayedQuestUpdate.UPDATE, qs, false); } } public void resetQuestProgress(int id, int infoNumber) { QuestStatus qs = getPlayer().getQuest(MapleQuest.getInstance(id)); if (qs != null) { qs.resetProgress(infoNumber); getPlayer().announceUpdateQuest(DelayedQuestUpdate.UPDATE, qs, false); } } public boolean forceStartQuest(int id) { return forceStartQuest(id, 9010000); } public boolean forceStartQuest(int id, int npc) { return startQuest(id, npc); } public boolean forceCompleteQuest(int id) { return forceCompleteQuest(id, 9010000); } public boolean forceCompleteQuest(int id, int npc) { return completeQuest(id, npc); } public boolean startQuest(short id) { return startQuest((int) id); } public boolean completeQuest(short id) { return completeQuest((int) id); } public boolean startQuest(int id) { return startQuest(id, 9010000); } public boolean completeQuest(int id) { return completeQuest(id, 9010000); } public boolean startQuest(short id, int npc) { return startQuest((int) id, npc); } public boolean completeQuest(short id, int npc) { return completeQuest((int) id, npc); } public boolean startQuest(int id, int npc) { try { return MapleQuest.getInstance(id).forceStart(getPlayer(), npc); } catch (NullPointerException ex) { ex.printStackTrace(); return false; } } public boolean completeQuest(int id, int npc) { try { return MapleQuest.getInstance(id).forceComplete(getPlayer(), npc); } catch (NullPointerException ex) { ex.printStackTrace(); return false; } } public Item evolvePet(byte slot, int afterId) { Pet evolved = null; Pet target; long period = (long) 90 * 24 * 60 * 60 * 1000; //refreshes expiration date: 90 days target = getPlayer().getPet(slot); if(target == null) { getPlayer().message("Pet could not be evolved..."); return(null); } Item tmp = gainItem(afterId, (short) 1, false, true, period, target); /* evolved = Pet.loadFromDb(tmp.getItemId(), tmp.getPosition(), tmp.getPetId()); evolved = tmp.getPet(); if(evolved == null) { getPlayer().message("Pet structure non-existent for " + tmp.getItemId() + "..."); return(null); } else if(tmp.getPetId() == -1) { getPlayer().message("Pet id -1"); return(null); } getPlayer().addPet(evolved); getPlayer().getMap().broadcastMessage(c.getPlayer(), PacketCreator.showPet(c.getPlayer(), evolved, false, false), true); c.sendPacket(PacketCreator.petStatUpdate(c.getPlayer())); c.sendPacket(PacketCreator.enableActions()); chr.getClient().getWorldServer().registerPetHunger(chr, chr.getPetIndex(evolved)); */ InventoryManipulator.removeFromSlot(c, InventoryType.CASH, target.getPosition(), (short) 1, false); return evolved; } public void gainItem(int id, short quantity) { gainItem(id, quantity, false, true); } public void gainItem(int id, short quantity, boolean show) {//this will fk randomStats equip :P gainItem(id, quantity, false, show); } public void gainItem(int id, boolean show) { gainItem(id, (short) 1, false, show); } public void gainItem(int id) { gainItem(id, (short) 1, false, true); } public Item gainItem(int id, short quantity, boolean randomStats, boolean showMessage) { return gainItem(id, quantity, randomStats, showMessage, -1); } public Item gainItem(int id, short quantity, boolean randomStats, boolean showMessage, long expires) { return gainItem(id, quantity, randomStats, showMessage, expires, null); } public Item gainItem(int id, short quantity, boolean randomStats, boolean showMessage, long expires, Pet from) { Item item = null; Pet evolved; int petId = -1; if (quantity >= 0) { if (ItemConstants.isPet(id)) { petId = Pet.createPet(id); if(from != null) { evolved = Pet.loadFromDb(id, (short) 0, petId); Point pos = getPlayer().getPosition(); pos.y -= 12; evolved.setPos(pos); evolved.setFh(getPlayer().getMap().getFootholds().findBelow(evolved.getPos()).getId()); evolved.setStance(0); evolved.setSummoned(true); evolved.setName(from.getName().compareTo(MapleItemInformationProvider.getInstance().getName(from.getItemId())) != 0 ? from.getName() : MapleItemInformationProvider.getInstance().getName(id)); evolved.setCloseness(from.getCloseness()); evolved.setFullness(from.getFullness()); evolved.setLevel(from.getLevel()); evolved.setExpiration(System.currentTimeMillis() + expires); evolved.saveToDb(); } //InventoryManipulator.addById(c, id, (short) 1, null, petId, expires == -1 ? -1 : System.currentTimeMillis() + expires); } MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); if (ItemConstants.getInventoryType(id).equals(InventoryType.EQUIP)) { item = ii.getEquipById(id); if(item != null) { Equip it = (Equip)item; if (ItemConstants.isAccessory(item.getItemId()) && it.getUpgradeSlots() <= 0) { it.setUpgradeSlots(3); } if(YamlConfig.config.server.USE_ENHANCED_CRAFTING == true && c.getPlayer().getCS() == true) { Equip eqp = (Equip)item; if(!(c.getPlayer().isGM() && YamlConfig.config.server.USE_PERFECT_GM_SCROLL)) { eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1)); } item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, 2049100, c.getPlayer().isGM()); } } } else { item = new Item(id, (short) 0, quantity, petId); } if (expires >= 0) { item.setExpiration(System.currentTimeMillis() + expires); } if (!InventoryManipulator.checkSpace(c, id, quantity, "")) { c.getPlayer().dropMessage(1, "Your inventory is full. Please remove an item from your " + ItemConstants.getInventoryType(id).name() + " inventory."); return null; } if (ItemConstants.getInventoryType(id) == InventoryType.EQUIP) { if (randomStats) { InventoryManipulator.addFromDrop(c, ii.randomizeStats((Equip) item), false, petId); } else { InventoryManipulator.addFromDrop(c, item, false, petId); } } else { InventoryManipulator.addFromDrop(c, item, false, petId); } } else { InventoryManipulator.removeById(c, ItemConstants.getInventoryType(id), id, -quantity, true, false); } if (showMessage) { c.sendPacket(PacketCreator.getShowItemGain(id, quantity, true)); } return item; } public void gainFame(int delta) { getPlayer().gainFame(delta); } public void changeMusic(String songName) { getPlayer().getMap().broadcastMessage(PacketCreator.musicChange(songName)); } public void playerMessage(int type, String message) { c.sendPacket(PacketCreator.serverNotice(type, message)); } public void message(String message) { getPlayer().message(message); } public void dropMessage(int type, String message) { getPlayer().dropMessage(type, message); } public void mapMessage(int type, String message) { getPlayer().getMap().broadcastMessage(PacketCreator.serverNotice(type, message)); } public void mapEffect(String path) { c.sendPacket(PacketCreator.mapEffect(path)); } public void mapSound(String path) { c.sendPacket(PacketCreator.mapSound(path)); } public void displayAranIntro() { String intro = ""; switch (c.getPlayer().getMapId()) { case 914090010: intro = "Effect/Direction1.img/aranTutorial/Scene0"; break; case 914090011: intro = "Effect/Direction1.img/aranTutorial/Scene1" + (c.getPlayer().getGender() == 0 ? "0" : "1"); break; case 914090012: intro = "Effect/Direction1.img/aranTutorial/Scene2" + (c.getPlayer().getGender() == 0 ? "0" : "1"); break; case 914090013: intro = "Effect/Direction1.img/aranTutorial/Scene3"; break; case 914090100: intro = "Effect/Direction1.img/aranTutorial/HandedPoleArm" + (c.getPlayer().getGender() == 0 ? "0" : "1"); break; case 914090200: intro = "Effect/Direction1.img/aranTutorial/Maha"; break; } showIntro(intro); } public void showIntro(String path) { c.sendPacket(PacketCreator.showIntro(path)); } public void showInfo(String path) { c.sendPacket(PacketCreator.showInfo(path)); c.sendPacket(PacketCreator.enableActions()); } public void guildMessage(int type, String message) { if (getGuild() != null) { getGuild().guildMessage(PacketCreator.serverNotice(type, message)); } } public MapleGuild getGuild() { try { return Server.getInstance().getGuild(getPlayer().getGuildId(), getPlayer().getWorld(), null); } catch (Exception e) { e.printStackTrace(); } return null; } public MapleParty getParty() { return getPlayer().getParty(); } public boolean isLeader() { return isPartyLeader(); } public boolean isGuildLeader() { return getPlayer().isGuildLeader(); } public boolean isPartyLeader() { if (getParty() == null) { return false; } return getParty().getLeaderId() == getPlayer().getId(); } public boolean isEventLeader() { return getEventInstance() != null && getPlayer().getId() == getEventInstance().getLeaderId(); } public void givePartyItems(int id, short quantity, List party) { for (Character chr : party) { Client cl = chr.getClient(); if (quantity >= 0) { InventoryManipulator.addById(cl, id, quantity); } else { InventoryManipulator.removeById(cl, ItemConstants.getInventoryType(id), id, -quantity, true, false); } cl.sendPacket(PacketCreator.getShowItemGain(id, quantity, true)); } } public void removeHPQItems() { int[] items = {4001095, 4001096, 4001097, 4001098, 4001099, 4001100, 4001101}; for (int item : items) { removePartyItems(item); } } public void removePartyItems(int id) { if (getParty() == null) { removeAll(id); return; } for (MaplePartyCharacter mpc : getParty().getMembers()) { if (mpc == null || !mpc.isOnline()) { continue; } Character chr = mpc.getPlayer(); if (chr != null && chr.getClient() != null){ removeAll(id, chr.getClient()); } } } public void giveCharacterExp(int amount, Character chr) { chr.gainExp((amount * chr.getExpRate()), true, true); } public void givePartyExp(int amount, List party) { for (Character chr : party) { giveCharacterExp(amount, chr); } } public void givePartyExp(String PQ) { givePartyExp(PQ, true); } public void givePartyExp(String PQ, boolean instance) { //1 player = +0% bonus (100) //2 players = +0% bonus (100) //3 players = +0% bonus (100) //4 players = +10% bonus (110) //5 players = +20% bonus (120) //6 players = +30% bonus (130) MapleParty party = getPlayer().getParty(); int size = party.getMembers().size(); if(instance) { for(MaplePartyCharacter member: party.getMembers()) { if(member == null || !member.isOnline()){ size--; } else { Character chr = member.getPlayer(); if(chr != null && chr.getEventInstance() == null) { size--; } } } } int bonus = size < 4 ? 100 : 70 + (size * 10); for (MaplePartyCharacter member : party.getMembers()) { if(member == null || !member.isOnline()){ continue; } Character player = member.getPlayer(); if(player == null) { continue; } if(instance && player.getEventInstance() == null){ continue; // They aren't in the instance, don't give EXP. } int base = PartyQuest.getExp(PQ, player.getLevel()); int exp = base * bonus / 100; player.gainExp(exp, true, true); if(YamlConfig.config.server.PQ_BONUS_EXP_RATE > 0 && System.currentTimeMillis() <= YamlConfig.config.server.EVENT_END_TIMESTAMP) { player.gainExp((int) (exp * YamlConfig.config.server.PQ_BONUS_EXP_RATE), true, true); } } } public void removeFromParty(int id, List party) { for (Character chr : party) { InventoryType type = ItemConstants.getInventoryType(id); Inventory iv = chr.getInventory(type); int possesed = iv.countById(id); if (possesed > 0) { InventoryManipulator.removeById(c, ItemConstants.getInventoryType(id), id, possesed, true, false); chr.sendPacket(PacketCreator.getShowItemGain(id, (short) -possesed, true)); } } } public void removeAll(int id) { removeAll(id, c); } public void removeAll(int id, Client cl) { InventoryType invType = ItemConstants.getInventoryType(id); int possessed = cl.getPlayer().getInventory(invType).countById(id); if (possessed > 0) { InventoryManipulator.removeById(cl, ItemConstants.getInventoryType(id), id, possessed, true, false); cl.sendPacket(PacketCreator.getShowItemGain(id, (short) -possessed, true)); } if(invType == InventoryType.EQUIP) { if(cl.getPlayer().getInventory(InventoryType.EQUIPPED).countById(id) > 0) { InventoryManipulator.removeById(cl, InventoryType.EQUIPPED, id, 1, true, false); cl.sendPacket(PacketCreator.getShowItemGain(id, (short) -1, true)); } } } public int getMapId() { return c.getPlayer().getMap().getId(); } public int getPlayerCount(int mapid) { return c.getChannelServer().getMapFactory().getMap(mapid).getCharacters().size(); } public void showInstruction(String msg, int width, int height) { c.sendPacket(PacketCreator.sendHint(msg, width, height)); c.sendPacket(PacketCreator.enableActions()); } public void disableMinimap() { c.sendPacket(PacketCreator.disableMinimap()); } public boolean isAllReactorState(final int reactorId, final int state) { return c.getPlayer().getMap().isAllReactorState(reactorId, state); } public void resetMap(int mapid) { getMap(mapid).resetReactors(); getMap(mapid).killAllMonsters(); for (MapleMapObject i : getMap(mapid).getMapObjectsInRange(c.getPlayer().getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.ITEM))) { getMap(mapid).removeMapObject(i); getMap(mapid).broadcastMessage(PacketCreator.removeItemFromMap(i.getObjectId(), 0, c.getPlayer().getId())); } } public void useItem(int id) { MapleItemInformationProvider.getInstance().getItemEffect(id).applyTo(c.getPlayer()); c.sendPacket(PacketCreator.getItemMessage(id));//Useful shet :3 } public void cancelItem(final int id) { getPlayer().cancelEffect(MapleItemInformationProvider.getInstance().getItemEffect(id), false, -1); } public void teachSkill(int skillid, byte level, byte masterLevel, long expiration) { teachSkill(skillid, level, masterLevel, expiration, false); } public void teachSkill(int skillid, byte level, byte masterLevel, long expiration, boolean force) { Skill skill = SkillFactory.getSkill(skillid); Character.SkillEntry skillEntry = getPlayer().getSkills().get(skill); if (skillEntry != null) { if (!force && level > -1) { getPlayer().changeSkillLevel(skill, (byte) Math.max(skillEntry.skillevel, level), Math.max(skillEntry.masterlevel, masterLevel), expiration == -1 ? -1 : Math.max(skillEntry.expiration, expiration)); return; } } else if (GameConstants.isAranSkills(skillid)) { c.sendPacket(PacketCreator.showInfo("Effect/BasicEff.img/AranGetSkill")); } getPlayer().changeSkillLevel(skill, level, masterLevel, expiration); } public void removeEquipFromSlot(short slot) { Item tempItem = c.getPlayer().getInventory(InventoryType.EQUIPPED).getItem(slot); InventoryManipulator.removeFromSlot(c, InventoryType.EQUIPPED, slot, tempItem.getQuantity(), false, false); } public void gainAndEquip(int itemid, short slot) { final Item old = c.getPlayer().getInventory(InventoryType.EQUIPPED).getItem(slot); if (old != null) { InventoryManipulator.removeFromSlot(c, InventoryType.EQUIPPED, slot, old.getQuantity(), false, false); } final Item newItem = MapleItemInformationProvider.getInstance().getEquipById(itemid); newItem.setPosition(slot); c.getPlayer().getInventory(InventoryType.EQUIPPED).addItemFromDB(newItem); c.sendPacket(PacketCreator.modifyInventory(false, Collections.singletonList(new ModifyInventory(0, newItem)))); } public void spawnNpc(int npcId, Point pos, MapleMap map) { MapleNPC npc = MapleLifeFactory.getNPC(npcId); if (npc != null) { npc.setPosition(pos); npc.setCy(pos.y); npc.setRx0(pos.x + 50); npc.setRx1(pos.x - 50); npc.setFh(map.getFootholds().findBelow(pos).getId()); map.addMapObject(npc); map.broadcastMessage(PacketCreator.spawnNPC(npc)); } } public void spawnMonster(int id, int x, int y) { MapleMonster monster = MapleLifeFactory.getMonster(id); monster.setPosition(new Point(x, y)); getPlayer().getMap().spawnMonster(monster); } public MapleMonster getMonsterLifeFactory(int mid) { return MapleLifeFactory.getMonster(mid); } public MobSkill getMobSkill(int skill, int level) { return MobSkillFactory.getMobSkill(skill, level); } public void spawnGuide() { c.sendPacket(PacketCreator.spawnGuide(true)); } public void removeGuide() { c.sendPacket(PacketCreator.spawnGuide(false)); } public void displayGuide(int num) { c.sendPacket(PacketCreator.showInfo("UI/tutorial.img/" + num)); } public void goDojoUp() { c.sendPacket(PacketCreator.dojoWarpUp()); } public void resetDojoEnergy() { c.getPlayer().setDojoEnergy(0); } public void resetPartyDojoEnergy() { for(Character pchr: c.getPlayer().getPartyMembersOnSameMap()) { pchr.setDojoEnergy(0); } } public void enableActions() { c.sendPacket(PacketCreator.enableActions()); } public void showEffect(String effect){ c.sendPacket(PacketCreator.showEffect(effect)); } public void dojoEnergy() { c.sendPacket(PacketCreator.getEnergy("energy", getPlayer().getDojoEnergy())); } public void talkGuide(String message) { c.sendPacket(PacketCreator.talkGuide(message)); } public void guideHint(int hint) { c.sendPacket(PacketCreator.guideHint(hint)); } public void updateAreaInfo(Short area, String info) { c.getPlayer().updateAreaInfo(area, info); c.sendPacket(PacketCreator.enableActions());//idk, nexon does the same :P } public boolean containsAreaInfo(short area, String info) { return c.getPlayer().containsAreaInfo(area, info); } public void earnTitle(String msg) { c.sendPacket(PacketCreator.earnTitleMessage(msg)); } public void showInfoText(String msg) { c.sendPacket(PacketCreator.showInfoText(msg)); } public void openUI(byte ui) { c.sendPacket(PacketCreator.openUI(ui)); } public void lockUI() { c.sendPacket(PacketCreator.disableUI(true)); c.sendPacket(PacketCreator.lockUI(true)); } public void unlockUI() { c.sendPacket(PacketCreator.disableUI(false)); c.sendPacket(PacketCreator.lockUI(false)); } public void playSound(String sound) { getPlayer().getMap().broadcastMessage(PacketCreator.environmentChange(sound, 4)); } public void environmentChange(String env, int mode) { getPlayer().getMap().broadcastMessage(PacketCreator.environmentChange(env, mode)); } public String numberWithCommas(int number) { return GameConstants.numberWithCommas(number); } public Pyramid getPyramid() { return (Pyramid) getPlayer().getPartyQuest(); } public int createExpedition(MapleExpeditionType type) { return createExpedition(type, false, 0, 0); } public int createExpedition(MapleExpeditionType type, boolean silent, int minPlayers, int maxPlayers) { Character player = getPlayer(); MapleExpedition exped = new MapleExpedition(player, type, silent, minPlayers, maxPlayers); int channel = player.getMap().getChannelServer().getId(); if (!MapleExpeditionBossLog.attemptBoss(player.getId(), channel, exped, false)) { // thanks Conrad for noticing missing expeditions entry limit return 1; } if (exped.addChannelExpedition(player.getClient().getChannelServer())) { return 0; } else { return -1; } } public void endExpedition(MapleExpedition exped) { exped.dispose(true); exped.removeChannelExpedition(getPlayer().getClient().getChannelServer()); } public MapleExpedition getExpedition(MapleExpeditionType type) { return getPlayer().getClient().getChannelServer().getExpedition(type); } public String getExpeditionMemberNames(MapleExpeditionType type) { String members = ""; MapleExpedition exped = getExpedition(type); for (String memberName : exped.getMembers().values()) { members += "" + memberName + ", "; } return members; } public boolean isLeaderExpedition(MapleExpeditionType type) { MapleExpedition exped = getExpedition(type); return exped.isLeader(getPlayer()); } public long getJailTimeLeft() { return getPlayer().getJailExpirationTimeLeft(); } public List getDriedPets() { List list = new LinkedList<>(); long curTime = System.currentTimeMillis(); for(Item it : getPlayer().getInventory(InventoryType.CASH).list()) { if(ItemConstants.isPet(it.getItemId()) && it.getExpiration() < curTime) { Pet pet = it.getPet(); if (pet != null) { list.add(pet); } } } return list; } public List getUnclaimedMarriageGifts() { return MapleMarriage.loadGiftItemsFromDb(this.getClient(), this.getPlayer().getId()); } public boolean startDungeonInstance(int dungeonid) { return c.getChannelServer().addMiniDungeon(dungeonid); } public boolean canGetFirstJob(int jobType) { if (YamlConfig.config.server.USE_AUTOASSIGN_STARTERS_AP) { return true; } Character chr = this.getPlayer(); switch(jobType) { case 1: return chr.getStr() >= 35; case 2: return chr.getInt() >= 20; case 3: case 4: return chr.getDex() >= 25; case 5: return chr.getDex() >= 20; default: return true; } } public String getFirstJobStatRequirement(int jobType) { switch(jobType) { case 1: return "STR " + 35; case 2: return "INT " + 20; case 3: case 4: return "DEX " + 25; case 5: return "DEX " + 20; } return null; } public void npcTalk(int npcid, String message) { c.sendPacket(PacketCreator.getNPCTalk(npcid, (byte) 0, message, "00 00", (byte) 0)); } public long getCurrentTime() { return Server.getInstance().getCurrentTime(); } }