Improved item & drop-point checking + Dojo fixes + Duey revamp

Fixed some issues with items being dropped sometimes out-of-reach and in a weird way.
Improved item checking function, now looking up one-of-a-kind items properly.
Fixed some issues with dojo skills and possible exploits in dojo progression.
Improved Duey, now displaying better info to players.
This commit is contained in:
ronancpl
2018-01-03 18:45:56 -02:00
parent 012f965f6a
commit 1190513d0c
69 changed files with 781 additions and 423 deletions
+23 -52
View File
@@ -25,6 +25,7 @@ import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import com.mysql.jdbc.Statement;
import constants.ItemConstants;
@@ -163,6 +164,10 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
}
}
private static boolean canBuy(MapleClient c, Item newItem) {
return MapleInventoryManipulator.checkSpace(c, newItem.getItemId(), newItem.getQuantity(), newItem.getOwner()) && MapleInventoryManipulator.addFromDrop(c, newItem, false);
}
public void buy(MapleClient c, int item, short quantity) {
synchronized (items) {
MaplePlayerShopItem pItem = items.get(item);
@@ -175,7 +180,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
if (quantity < 1 || pItem.getBundles() < 1 || !pItem.isExist() || pItem.getBundles() < quantity) {
c.announce(MaplePacketCreator.enableActions());
return;
} else if (newItem.getType() == 1 && newItem.getQuantity() > 1) {
} else if (newItem.getInventoryType().equals(MapleInventoryType.EQUIP) && newItem.getQuantity() > 1) {
c.announce(MaplePacketCreator.enableActions());
return;
} else if (!pItem.isExist()) {
@@ -185,8 +190,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
int price = (int) Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
if (c.getPlayer().getMeso() >= price) {
if (MapleInventoryManipulator.checkSpace(c, newItem.getItemId(), newItem.getQuantity(), newItem.getOwner())) {
MapleInventoryManipulator.addFromDrop(c, newItem, false);
if (canBuy(c, newItem)) {
c.getPlayer().gainMeso(-price, false);
announceItemSold(newItem, price); // idea thanks to vcoc
@@ -216,7 +220,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
}
}
} else {
c.getPlayer().dropMessage(1, "Your inventory is full. Please clear a slot before buying this item.");
c.getPlayer().dropMessage(1, "Your inventory is full. Please clean a slot before buying this item.");
}
} else {
c.getPlayer().dropMessage(1, "You do not have enough mesos.");
@@ -231,11 +235,10 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
private void announceItemSold(Item item, int mesos) {
String qtyStr = (item.getQuantity() > 1) ? " (qty. " + item.getQuantity() + ")" : "";
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleCharacter player = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId);
if(player != null && player.isLoggedin() && !player.isAwayFromWorld()) {
player.dropMessage(6, "[HIRED MERCHANT] Item '" + ii.getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
player.dropMessage(6, "[HIRED MERCHANT] Item '" + MapleItemInformationProvider.getInstance().getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
}
}
@@ -296,10 +299,12 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
List<MaplePlayerShopItem> copyItems = getItems();
if (check(c.getPlayer(), copyItems) && !timeout) {
for (MaplePlayerShopItem mpsi : copyItems) {
if (mpsi.isExist() && (mpsi.getItem().getType() == MapleInventoryType.EQUIP.getType())) {
MapleInventoryManipulator.addFromDrop(c, mpsi.getItem(), false);
} else if (mpsi.isExist()) {
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), null, -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
if(mpsi.isExist()) {
if (mpsi.getItem().getInventoryType().equals(MapleInventoryType.EQUIP)) {
MapleInventoryManipulator.addFromDrop(c, mpsi.getItem(), false);
} else {
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), null, -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
}
}
}
@@ -465,7 +470,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
newItem.setQuantity((short) (pItems.getItem().getQuantity()));
}
if (newBundle > 0) {
itemsWithType.add(new Pair<>(newItem, MapleInventoryType.getByType(newItem.getType())));
itemsWithType.add(new Pair<>(newItem, newItem.getInventoryType()));
bundles.add(newBundle);
}
}
@@ -476,49 +481,15 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
}
private static boolean check(MapleCharacter chr, List<MaplePlayerShopItem> items) {
byte eq = 0, use = 0, setup = 0, etc = 0, cash = 0;
List<MapleInventoryType> li = new LinkedList<>();
List<Pair<Item, MapleInventoryType>> li = new ArrayList<>();
for (MaplePlayerShopItem item : items) {
final MapleInventoryType invtype = MapleItemInformationProvider.getInstance().getInventoryType(item.getItem().getItemId());
if (!li.contains(invtype)) {
li.add(invtype);
}
if (invtype == MapleInventoryType.EQUIP) {
eq++;
} else if (invtype == MapleInventoryType.USE) {
use++;
} else if (invtype == MapleInventoryType.SETUP) {
setup++;
} else if (invtype == MapleInventoryType.ETC) {
etc++;
} else if (invtype == MapleInventoryType.CASH) {
cash++;
}
Item it = item.getItem().copy();
it.setQuantity((short)(it.getQuantity() * item.getBundles()));
li.add(new Pair<>(it, it.getInventoryType()));
}
for (MapleInventoryType mit : li) {
if (mit == MapleInventoryType.EQUIP) {
if (chr.getInventory(MapleInventoryType.EQUIP).getNumFreeSlot() <= eq) {
return false;
}
} else if (mit == MapleInventoryType.USE) {
if (chr.getInventory(MapleInventoryType.USE).getNumFreeSlot() <= use) {
return false;
}
} else if (mit == MapleInventoryType.SETUP) {
if (chr.getInventory(MapleInventoryType.SETUP).getNumFreeSlot() <= setup) {
return false;
}
} else if (mit == MapleInventoryType.ETC) {
if (chr.getInventory(MapleInventoryType.ETC).getNumFreeSlot() <= etc) {
return false;
}
} else if (mit == MapleInventoryType.CASH) {
if (chr.getInventory(MapleInventoryType.CASH).getNumFreeSlot() <= cash) {
return false;
}
}
}
return true;
return MapleInventory.checkSpotsAndOwnership(chr, li);
}
public int getChannel() {
+65 -22
View File
@@ -560,27 +560,28 @@ public class MapleMap {
return new Pair(getRoundedCoordinate(angle), Integer.valueOf((int)distn));
}
private void dropFromMonster(final MapleCharacter chr, final MapleMonster mob) {
if (mob.dropsDisabled() || !dropsOn) {
return;
private static void sortDropEntries(List<MonsterDropEntry> from, List<MonsterDropEntry> item, List<MonsterDropEntry> quest) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for(MonsterDropEntry mde : from) {
if(mde.itemId == 0 || !ii.isQuestItem(mde.itemId)) {
item.add(mde);
} else {
quest.add(mde);
}
}
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
final byte droptype = (byte) (mob.getStats().isExplosiveReward() ? 3 : mob.getStats().isFfaLoot() ? 2 : chr.getParty() != null ? 1 : 0);
final int mobpos = mob.getPosition().x;
int chRate = chr.getDropRate();
Item idrop;
byte d = 1;
Point pos = new Point(0, mob.getPosition().y);
MonsterStatusEffect stati = mob.getStati(MonsterStatus.SHOWDOWN);
if (stati != null) {
chRate *= (stati.getStati().get(MonsterStatus.SHOWDOWN).doubleValue() / 100.0 + 1.0);
}
private byte dropItemsFromMonsterOnMap(List<MonsterDropEntry> dropEntry, Point pos, byte d, int chRate, byte droptype, int mobpos, MapleCharacter chr, MapleMonster mob) {
if(dropEntry.isEmpty()) {
return d;
}
final MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
final List<MonsterDropEntry> dropEntry = new ArrayList<>(mi.retrieveDrop(mob.getId()));
Collections.shuffle(dropEntry);
Item idrop;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (final MonsterDropEntry de : dropEntry) {
if (Randomizer.nextInt(999999) < de.chance * chRate) {
if (droptype == 3) {
@@ -611,8 +612,16 @@ public class MapleMap {
d++;
}
}
final List<MonsterGlobalDropEntry> globalEntry = mi.getGlobalDrop();
// Global Drops
return d;
}
private byte dropGlobalItemsFromMonsterOnMap(List<MonsterGlobalDropEntry> globalEntry, Point pos, byte d, byte droptype, int mobpos, MapleCharacter chr, MapleMonster mob) {
Collections.shuffle(globalEntry);
Item idrop;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (final MonsterGlobalDropEntry de : globalEntry) {
if (Randomizer.nextInt(999999) < de.chance) {
if (droptype == 3) {
@@ -631,6 +640,40 @@ public class MapleMap {
}
}
}
return d;
}
private void dropFromMonster(final MapleCharacter chr, final MapleMonster mob) {
if (mob.dropsDisabled() || !dropsOn) {
return;
}
final byte droptype = (byte) (mob.getStats().isExplosiveReward() ? 3 : mob.getStats().isFfaLoot() ? 2 : chr.getParty() != null ? 1 : 0);
final int mobpos = mob.getPosition().x;
int chRate = chr.getDropRate();
byte d = 1;
Point pos = new Point(0, mob.getPosition().y);
MonsterStatusEffect stati = mob.getStati(MonsterStatus.SHOWDOWN);
if (stati != null) {
chRate *= (stati.getStati().get(MonsterStatus.SHOWDOWN).doubleValue() / 100.0 + 1.0);
}
final MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
final List<MonsterDropEntry> dropEntry = new ArrayList<>();
final List<MonsterDropEntry> questEntry = new ArrayList<>();
sortDropEntries(mi.retrieveDrop(mob.getId()), dropEntry, questEntry);
// Normal Drops
d = dropItemsFromMonsterOnMap(dropEntry, pos, d, chRate, droptype, mobpos, chr, mob);
// Global Drops
final List<MonsterGlobalDropEntry> globalEntry = mi.getGlobalDrop();
d = dropGlobalItemsFromMonsterOnMap(globalEntry, pos, d, droptype, mobpos, chr, mob);
// Quest Drops
dropItemsFromMonsterOnMap(questEntry, pos, d, chRate, droptype, mobpos, chr, mob);
}
public void dropFromReactor(final MapleCharacter chr, final MapleReactor reactor, Item drop, Point dropPos, short questid) {
@@ -1852,7 +1895,7 @@ public class MapleMap {
final Item drop;
int randomedId = list.get(i);
if (ii.getInventoryType(randomedId) != MapleInventoryType.EQUIP) {
if (ItemConstants.getInventoryType(randomedId) != MapleInventoryType.EQUIP) {
drop = new Item(randomedId, (short) 0, (short) (rnd.nextInt(copies) + minCopies));
} else {
drop = ii.randomizeStats((Equip) ii.getEquipById(randomedId));
@@ -2567,7 +2610,7 @@ public class MapleMap {
}
public void setMapPointBoundings(int px, int py, int h, int w) {
mapArea.setBounds(px + 7, py, w - 14, h);
mapArea.setBounds(px + 45, py, w - 90, h);
}
public void setMapLineBoundings(int vrTop, int vrBottom, int vrLeft, int vrRight) {
+3
View File
@@ -144,6 +144,9 @@ public class MapleMapFactory {
bounds[3] = MapleDataTool.getInt(minimapData.getChildByPath("width"));
map.setMapPointBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
} else {
int dist = (1 << 18);
map.setMapPointBoundings(-dist / 2, -dist / 2, dist, dist);
}
} else {
bounds[2] = MapleDataTool.getInt(infoData.getChildByPath("VRLeft"));
+8 -4
View File
@@ -24,6 +24,7 @@ package server.maps;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
@@ -187,6 +188,10 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
}
}
private static boolean canBuy(MapleClient c, Item newItem) {
return MapleInventoryManipulator.checkSpace(c, newItem.getItemId(), newItem.getQuantity(), newItem.getOwner()) && MapleInventoryManipulator.addFromDrop(c, newItem, false);
}
/**
* no warnings for now o.o
* @param c
@@ -201,14 +206,14 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
newItem.setQuantity(newItem.getQuantity());
if (quantity < 1 || pItem.getBundles() < 1 || newItem.getQuantity() > pItem.getBundles() || !pItem.isExist()) {
return;
} else if (newItem.getType() == 1 && newItem.getQuantity() > 1) {
} else if (newItem.getInventoryType().equals(MapleInventoryType.EQUIP) && newItem.getQuantity() > 1) {
return;
}
synchronized (c.getPlayer()) {
int price = (int) Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
if (c.getPlayer().getMeso() >= price) {
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
if (canBuy(c, newItem)) {
c.getPlayer().gainMeso(-price, false);
announceItemSold(newItem, price); // idea thanks to vcoc
@@ -235,9 +240,8 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
private void announceItemSold(Item item, int mesos) {
String qtyStr = (item.getQuantity() > 1) ? " (qty. " + item.getQuantity() + ")" : "";
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
owner.dropMessage(6, "[PLAYER SHOP] Item '" + ii.getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
owner.dropMessage(6, "[PLAYER SHOP] Item '" + MapleItemInformationProvider.getInstance().getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
}
public void broadcastToVisitors(final byte[] packet) {