Meso patch + Swift Dmg Reflect buff + GPQ Rewards + Starting Q. items

Fixed several RNG pool issues within several handler classes.
Fixed an overflow issue with mesos, that would cause players to lose all amount on inventory.
Changed the code coupon SQL structure. Now nxcode_items.quantity is to be specified for both nx values and item quantities alike, instead of the use of "quantity" only when items are being provided.
Bob Snail now appears each 4 hours, instead of any time.
Removed duplicate command Warpto. Warpto merged with Reach command.
Fixed solo expeditions being disposed for "lack of personnel" after changing maps (normal limitations should not apply when USE_ENABLE_SOLO_EXPEDITIONS is enabled).
Fixed mobskills "Weapon/Magic Reflect" taking too long to show the active status over the mob's head.
Fixed a case with clean slate scroll not working as expected.
Improved reward contents for the GPQ.
Fixed loot manager not acting properly when verifying one-of-a-kind contents.
Implemented quest item requirement checkups to start quests. Items required to start a quest now should appear if the player did not start it yet, e.g.: SOS letter.
Fixed an issue with server message/boss HPbar switch interaction that would not work the moment after a player changed channels/entered Cash Shop.
Improved Victoria Island worldmap design, at the Kerning subway area.
This commit is contained in:
ronancpl
2018-12-05 02:52:14 -02:00
parent 0910dc2428
commit a17c233693
53 changed files with 625 additions and 343 deletions
+13 -6
View File
@@ -1583,7 +1583,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
this.unregisterChairBuff();
this.clearBanishPlayerData();
this.closePlayerInteractions();
this.resetPlayerAggro();
client.announce(warpPacket);
map.removePlayer(this);
@@ -2001,7 +2000,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public static boolean deleteCharFromDB(MapleCharacter player, int senderAccId) {
int cid = player.getId();
if(!Server.getInstance().haveCharacterEntry(senderAccId, cid)) {
if(!Server.getInstance().haveCharacterEntry(senderAccId, cid)) { // thanks zera (EpiphanyMS) for pointing a critical exploit with non-authored character deletion request
return false;
}
@@ -2979,7 +2978,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
long nextMeso;
petLock.lock();
try {
nextMeso = meso.get() + gain;
nextMeso = (long) meso.get() + gain; // thanks Thora for pointing integer overflow here
if (nextMeso > Integer.MAX_VALUE) {
gain -= (nextMeso - Integer.MAX_VALUE);
} else if (nextMeso < 0) {
@@ -4933,6 +4932,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
closePlayerMessenger();
client.closePlayerScriptInteractions();
resetPlayerAggro();
}
public void closeNpcShop() {
@@ -5140,10 +5140,17 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public boolean needQuestItem(int questid, int itemid) {
if (questid <= 0) return true; //For non quest items :3
if (this.getQuestStatus(questid) != 1) return false;
MapleQuest quest = MapleQuest.getInstance(questid);
return getInventory(ItemConstants.getInventoryType(itemid)).countById(itemid) < quest.getItemAmountNeeded(itemid);
int amountNeeded, questStatus = this.getQuestStatus(questid);
if (questStatus == 0) {
amountNeeded = MapleQuest.getInstance(questid).getStartItemAmountNeeded(itemid);
} else if (questStatus != 1) {
return false;
} else {
amountNeeded = MapleQuest.getInstance(questid).getCompleteItemAmountNeeded(itemid);
}
return amountNeeded > 0 && getInventory(ItemConstants.getInventoryType(itemid)).countById(itemid) < amountNeeded;
}
public int getRank() {
+1 -2
View File
@@ -217,9 +217,8 @@ public class CommandsExecutor {
addCommand("cleardrops", 2, ClearDropsCommand.class);
addCommand("clearslot", 2, ClearSlotCommand.class);
addCommand("warp", 2, WarpCommand.class);
addCommand("warpto", 2, WarpToCommand.class);
addCommand(new String[]{"warphere", "summon"}, 2, SummonCommand.class);
addCommand(new String[]{"reach", "follow"}, 2, ReachCommand.class);
addCommand(new String[]{"warpto", "reach", "follow"}, 2, ReachCommand.class);
addCommand("gmshop", 2, GmShopCommand.class);
addCommand("heal", 2, HealCommand.class);
addCommand("item", 2, ItemCommand.class);
@@ -1,78 +0,0 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2018 RonanLana
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 <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import net.server.Server;
import net.server.channel.Channel;
public class WarpToCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 2) {
player.yellowMessage("Syntax: !warpto <playername> <mapid>");
return;
}
MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim == null) {//If victim isn't on current channel or isnt a character try and find him by loop all channels on current world.
for (Channel ch : Server.getInstance().getChannelsFromWorld(c.getWorld())) {
victim = ch.getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
break;//We found the person, no need to continue the loop.
}
}
}
if (victim != null) {//If target isn't null attempt to warp.
//Remove warper from current event instance.
if (player.getEventInstance() != null) {
player.getEventInstance().unregisterPlayer(player);
}
//Attempt to join the victims warp instance.
if (victim.getEventInstance() != null) {
if (victim.getClient().getChannel() == player.getClient().getChannel()) {//just in case.. you never know...
//victim.getEventInstance().registerPlayer(player);
player.changeMap(victim.getEventInstance().getMapInstance(victim.getMapId()), victim.getMap().findClosestPortal(victim.getPosition()));
} else {
player.dropMessage(6, "Please change to channel " + victim.getClient().getChannel());
}
} else {//If victim isn't in an event instance, just warp them.
player.changeMap(victim.getMapId(), victim.getMap().findClosestPortal(victim.getPosition()));
}
if (player.getClient().getChannel() != victim.getClient().getChannel()) {//And then change channel if needed.
player.dropMessage("Changing channel, please wait a moment.");
player.getClient().changeChannel(victim.getClient().getChannel());
}
} else {
player.dropMessage(6, "Unknown player.");
}
}
}
@@ -40,18 +40,35 @@ public class GiveMesosCommand extends Command {
return;
}
String recv_;
int value_;
String recv_, value_;
long mesos_ = 0;
if (params.length == 2) {
recv_ = params[0];
value_ = Integer.parseInt(params[1]);
value_ = params[1];
} else {
recv_ = c.getPlayer().getName();
value_ = Integer.parseInt(params[0]);
value_ = params[0];
}
try {
mesos_ = Long.parseLong(value_);
if (mesos_ > Integer.MAX_VALUE) {
mesos_ = Integer.MAX_VALUE;
} else if (mesos_ < Integer.MIN_VALUE) {
mesos_ = Integer.MIN_VALUE;
}
} catch (NumberFormatException nfe) {
if (value_.contentEquals("max")) { // "max" descriptor suggestion thanks to Vcoc
mesos_ = Integer.MAX_VALUE;
} else if (value_.contentEquals("min")) {
mesos_ = Integer.MIN_VALUE;
}
}
MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(recv_);
if (victim != null) {
victim.gainMeso(value_, true);
victim.gainMeso((int) mesos_, true);
player.message("MESO given.");
} else {
player.message("Player '" + recv_ + "' could not be found on this channel.");
+1 -1
View File
@@ -7,7 +7,7 @@
package constants;
/*
* Courtesy of GabrielSin ([email protected])
* Thanks to GabrielSin (EllinMS) - [email protected]
* Ellin
* MapleStory Server
* CharsetConstants
+3 -3
View File
@@ -71,8 +71,6 @@ public class GameConstants {
put("ellin", 300000000);
put("nlc", 600000000);
put("excavation", 990000000);
put("pianus", 230040420);
put("horntail", 240060200);
put("mushmom", 100000005);
put("griffey", 240020101);
put("manon", 240020401);
@@ -85,7 +83,9 @@ public class GameConstants {
put("shrine", 800000000);
put("skelegon", 240040511);
put("hpq", 100000200);
put("ht", 240050400);
put("pianus", 230040420);
put("horntail", 240050400);
put("pinkbean", 270050000);
put("ariant", 260000000);
put("magatia", 261000000);
put("singapore", 540000000);
+1
View File
@@ -261,6 +261,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.WATER_OF_LIFE, new UseWaterOfLifeHandler());
registerHandler(RecvOpcode.ADMIN_CHAT, new AdminChatHandler());
registerHandler(RecvOpcode.MOVE_DRAGON, new MoveDragonHandler());
registerHandler(RecvOpcode.USE_ITEMUI, new UseItemCanvasHandler());
}
}
}
+3 -3
View File
@@ -188,9 +188,9 @@ public enum RecvOpcode {
CHECK_CASH(0xE4),
CASHSHOP_OPERATION(0xE5),
COUPON_CODE(0xE6),
OPEN_ITEMUI(0xEB),
CLOSE_ITEMUI(0xEC),
USE_ITEMUI(0xED),
OPEN_ITEMUI(0xEC),
CLOSE_ITEMUI(0xED),
USE_ITEMUI(0xEE),
MTS_OPERATION(0xFD),
USE_MAPLELIFE(0x100),
USE_HAMMER(0x104);
+79 -78
View File
@@ -569,7 +569,7 @@ public class Server {
}
public List<Integer> getActiveCoupons() {
synchronized(activeCoupons) {
synchronized (activeCoupons) {
return activeCoupons;
}
}
@@ -586,7 +586,7 @@ public class Server {
public void toggleCoupon(Integer couponId) {
if(ItemConstants.isRateCoupon(couponId)) {
synchronized(activeCoupons) {
synchronized (activeCoupons) {
if(activeCoupons.contains(couponId)) {
activeCoupons.remove(couponId);
}
@@ -600,7 +600,7 @@ public class Server {
}
public void updateActiveCoupons() throws SQLException {
synchronized(activeCoupons) {
synchronized (activeCoupons) {
activeCoupons.clear();
Calendar c = Calendar.getInstance();
@@ -1669,9 +1669,10 @@ public class Server {
}
private void disconnectIdlesOnLoginState() {
List<MapleClient> toDisconnect = new LinkedList<>();
srvLock.lock();
try {
List<MapleClient> toDisconnect = new LinkedList<>();
long timeNow = System.currentTimeMillis();
for(Entry<MapleClient, Long> mc : inLoginState.entrySet()) {
@@ -1681,17 +1682,19 @@ public class Server {
}
for(MapleClient c : toDisconnect) {
if(c.isLoggedIn()) {
c.disconnect(false, false);
} else {
c.getSession().close(true);
}
inLoginState.remove(c);
}
} finally {
srvLock.unlock();
}
for (MapleClient c : toDisconnect) { // thanks Lei for pointing a deadlock issue with srvLock
if(c.isLoggedIn()) {
c.disconnect(false, false);
} else {
c.getSession().close(true);
}
}
}
private void disconnectIdlesOnLoginTask() {
@@ -1707,75 +1710,73 @@ public class Server {
return new Runnable() {
@Override
public void run() {
srvLock.lock();
try {
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
if (getWorlds() == null) return;//already shutdown
for (World w : getWorlds()) {
w.shutdown();
}
/*for (World w : getWorlds()) {
while (w.getPlayerStorage().getAllCharacters().size() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
System.err.println("FUCK MY LIFE");
}
}
}
for (Channel ch : getAllChannels()) {
while (ch.getConnectedClients() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
System.err.println("FUCK MY LIFE");
}
}
}*/
List<Channel> allChannels = getAllChannels();
if(ServerConstants.USE_THREAD_TRACKER) ThreadTracker.getInstance().cancelThreadTrackerTask();
for (Channel ch : allChannels) {
while (!ch.finishedShutdown()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
System.err.println("FUCK MY LIFE");
}
}
}
resetServerWorlds();
ThreadManager.getInstance().stop();
TimerManager.getInstance().purge();
TimerManager.getInstance().stop();
System.out.println("Worlds + Channels are offline.");
acceptor.unbind();
acceptor = null;
if (!restart) {
System.exit(0);
} else {
System.out.println("\r\nRestarting the server....\r\n");
try {
instance.finalize();//FUU I CAN AND IT'S FREE
} catch (Throwable ex) {
ex.printStackTrace();
}
instance = null;
System.gc();
getInstance().init();//DID I DO EVERYTHING?! D:
}
} finally {
srvLock.unlock();
}
shutdownInternal(restart);
}
};
}
private synchronized void shutdownInternal(boolean restart) {
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
if (getWorlds() == null) return;//already shutdown
for (World w : getWorlds()) {
w.shutdown();
}
/*for (World w : getWorlds()) {
while (w.getPlayerStorage().getAllCharacters().size() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
System.err.println("FUCK MY LIFE");
}
}
}
for (Channel ch : getAllChannels()) {
while (ch.getConnectedClients() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
System.err.println("FUCK MY LIFE");
}
}
}*/
List<Channel> allChannels = getAllChannels();
if(ServerConstants.USE_THREAD_TRACKER) ThreadTracker.getInstance().cancelThreadTrackerTask();
for (Channel ch : allChannels) {
while (!ch.finishedShutdown()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
System.err.println("FUCK MY LIFE");
}
}
}
resetServerWorlds();
ThreadManager.getInstance().stop();
TimerManager.getInstance().purge();
TimerManager.getInstance().stop();
System.out.println("Worlds + Channels are offline.");
acceptor.unbind();
acceptor = null;
if (!restart) {
System.exit(0);
} else {
System.out.println("\r\nRestarting the server....\r\n");
try {
instance.finalize();//FUU I CAN AND IT'S FREE
} catch (Throwable ex) {
ex.printStackTrace();
}
instance = null;
System.gc();
getInstance().init();//DID I DO EVERYTHING?! D:
}
}
}
@@ -55,7 +55,7 @@ public final class AdminCommandHandler extends AbstractMaplePacketHandler {
int[][] toSpawn = MapleItemInformationProvider.getInstance().getSummonMobs(slea.readInt());
for (int z = 0; z < toSpawn.length; z++) {
int[] toSpawnChild = toSpawn[z];
if (Randomizer.nextInt(101) <= toSpawnChild[1]) {
if (Randomizer.nextInt(100) < toSpawnChild[1]) {
c.getPlayer().getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(toSpawnChild[0]), c.getPlayer().getPosition());
}
}
@@ -62,17 +62,17 @@ public final class CouponCodeHandler extends AbstractMaplePacketHandler {
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int type = rs.getInt("type"), item = rs.getInt("item");
int type = rs.getInt("type"), quantity = rs.getInt("quantity");
if (type < 5) {
Integer i = couponPoints.get(type);
if (i != null) {
couponPoints.put(type, i + item);
couponPoints.put(type, i + quantity);
} else {
couponPoints.put(type, item);
couponPoints.put(type, quantity);
}
} else {
int quantity = rs.getInt("quantity");
int item = rs.getInt("item");
Integer i = couponItems.get(item);
if (i != null) {
@@ -108,7 +108,7 @@ public final class CouponCodeHandler extends AbstractMaplePacketHandler {
if (!couponPoints.isEmpty()) {
for (Entry<Integer, Integer> e : couponPoints.entrySet()) {
ret.add(new Pair<>(e.getKey(), new Pair<>(e.getValue(), 777)));
ret.add(new Pair<>(e.getKey(), new Pair<>(777, e.getValue())));
}
}
@@ -199,27 +199,37 @@ public final class CouponCodeHandler extends AbstractMaplePacketHandler {
for (Pair<Integer, Pair<Integer, Integer>> p : codeRes.getRight()) {
type = p.getLeft();
int item = p.getRight().getLeft();
int quantity = p.getRight().getRight();
CashShop cs = c.getPlayer().getCashShop();
switch (type) {
case 0:
case 4:
cs.gainCash(1, item); //nxCredit
cs.gainCash(1, quantity); //nxCredit
break;
case 1:
cs.gainCash(2, item); //maplePoint
cs.gainCash(2, quantity); //maplePoint
break;
case 2:
cs.gainCash(4, item); //nxPrepaid
cs.gainCash(4, quantity); //nxPrepaid
break;
case 3:
cs.gainCash(1, item);
cs.gainCash(4, (item / 5000));
cs.gainCash(1, quantity);
cs.gainCash(4, (quantity / 5000));
break;
default:
short qty = p.getRight().getRight().shortValue();
int item = p.getRight().getLeft();
short qty;
if (quantity > Short.MAX_VALUE) {
qty = Short.MAX_VALUE;
} else if (quantity < Short.MIN_VALUE) {
qty = Short.MIN_VALUE;
} else {
qty = (short) quantity;
}
if (MapleItemInformationProvider.getInstance().isCash(item)) {
Item it = CashShop.generateCouponItem(item, qty);
@@ -86,6 +86,8 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
return;
}
chr.closePlayerInteractions();
chr.unregisterChairBuff();
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
@@ -43,7 +43,7 @@ public final class HealOvertimeHandler extends AbstractMaplePacketHandler {
short healHP = slea.readShort();
if (healHP != 0) {
abm.setTimestamp(8, timestamp, 4); // thanks Vcoc for pointing out d/c happening here
abm.setTimestamp(8, timestamp, 28); // thanks Vcoc & Thora for pointing out d/c happening here
if ((abm.getLastSpam(0) + 1500) > timestamp) AutobanFactory.FAST_HP_HEALING.addPoint(abm, "Fast hp healing");
int abHeal = 120 + (int)(20 * MapleMapFactory.getMapRecoveryRate(chr.getMapId())); // Sleepywood sauna and showa spa...
@@ -58,7 +58,7 @@ public final class HealOvertimeHandler extends AbstractMaplePacketHandler {
}
short healMP = slea.readShort();
if (healMP != 0 && healMP < 1000) {
abm.setTimestamp(9, timestamp, 4);
abm.setTimestamp(9, timestamp, 28);
if ((abm.getLastSpam(1) + 1500) > timestamp) AutobanFactory.FAST_MP_HEALING.addPoint(abm, "Fast mp healing");
chr.addMP(healMP);
abm.spam(1, timestamp);
@@ -37,7 +37,9 @@ import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Ronan - header layout courtesy of Eric
* @author Ronan
*
* Header layout thanks to Eric
*/
public final class NewYearCardHandler extends AbstractMaplePacketHandler {
@@ -52,7 +52,7 @@ public final class PetCommandHandler extends AbstractMaplePacketHandler {
return;
}
if (Randomizer.nextInt(101) <= petCommand.getProbability()) {
if (Randomizer.nextInt(100) < petCommand.getProbability()) {
pet.gainClosenessFullness(chr, petCommand.getIncrease(), 0, command);
chr.getMap().broadcastMessage(MaplePacketCreator.commandResponse(chr.getId(), petIndex, false, command, false));
} else {
@@ -36,7 +36,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
*/
public final class QuestActionHandler extends AbstractMaplePacketHandler {
// isNpcNearby credits to gabriel.sin
// isNpcNearby credits to GabrielSin
private static boolean isNpcNearby(SeekableLittleEndianAccessor slea, MapleCharacter player, MapleQuest quest, int npcId) {
Point playerP = null;
@@ -74,7 +74,7 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
Item wscroll = null;
if (ItemConstants.isCleanSlate(scroll.getItemId())) {
Map<String, Integer> eqStats = ii.getEquipStats(scroll.getItemId());
Map<String, Integer> eqStats = ii.getEquipStats(toScroll.getItemId()); // clean slate issue found thanks to Masterrulax
if (eqStats == null || eqStats.get("tuc") == 0) {
c.announce(MaplePacketCreator.getInventoryFull());
return;
@@ -106,7 +106,7 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
for (loseItem loseItem : loseItems) {
type = ItemConstants.getInventoryType(loseItem.getId());
for (byte b = 0; b < loseItem.getX(); b++) {//LOL?
if (Randomizer.nextInt(101) >= loseItem.getChance()) {
if (Randomizer.nextInt(100) < loseItem.getChance()) {
if (chr.haveItem(loseItem.getId())) {
pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
@@ -0,0 +1,14 @@
package net.server.channel.handlers;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.MaplePacketCreator;
public final class UseItemCanvasHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
c.announce(MaplePacketCreator.enableActions());
}
}
@@ -54,7 +54,7 @@ public final class UseSummonBagHandler extends AbstractMaplePacketHandler {
int[][] toSpawn = MapleItemInformationProvider.getInstance().getSummonMobs(itemId);
for (int z = 0; z < toSpawn.length; z++) {
int[] toSpawnChild = toSpawn[z];
if (Randomizer.nextInt(101) <= toSpawnChild[1]) {
if (Randomizer.nextInt(100) < toSpawnChild[1]) {
c.getPlayer().getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(toSpawnChild[0]), c.getPlayer().getPosition());
}
}
@@ -1111,6 +1111,17 @@ public class EventInstanceManager {
return false;
}
public final boolean isExpeditionTeamLackingNow(boolean leavingEventMap, int minPlayers, MapleCharacter quitter) {
if(eventCleared) {
if(leavingEventMap && getPlayerCount() <= 1) return true;
} else {
if(leavingEventMap && getLeaderId() == quitter.getId()) return true;
if(getPlayerCount() <= (ServerConstants.USE_ENABLE_SOLO_EXPEDITIONS ? 1 : minPlayers)) return true;
}
return false;
}
public final boolean isEventTeamLackingNow(boolean leavingEventMap, int minPlayers, MapleCharacter quitter) {
if(eventCleared) {
if(leavingEventMap && getPlayerCount() <= 1) return true;
+10 -3
View File
@@ -1001,7 +1001,7 @@ public class MapleItemInformationProvider {
if (!ServerConstants.USE_PERFECT_SCROLLING && !usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
}
if (Randomizer.nextInt(101) < stats.get("cursed")) {
if (Randomizer.nextInt(100) < stats.get("cursed")) {
return null;
}
}
@@ -1258,8 +1258,15 @@ public class MapleItemInformationProvider {
if (pickupRestrictionCache.containsKey(itemId)) {
return pickupRestrictionCache.get(itemId);
}
MapleData data = getItemData(itemId);
boolean bRestricted = MapleDataTool.getIntConvert("info/only", data, 0) == 1;
boolean bRestricted = false;
if(itemId != 0) {
MapleData data = getItemData(itemId);
if (data != null) {
bRestricted = MapleDataTool.getIntConvert("info/only", data, 0) == 1;
}
}
pickupRestrictionCache.put(itemId, bRestricted);
return bRestricted;
}
+8 -3
View File
@@ -1303,7 +1303,8 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
int useLimit = toUse.getLimit();
if (toUse.getSkillId() == 200) {
int useSkillid = toUse.getSkillId();
if (useSkillid == 200) {
int i = 0;
for (MapleMapObject mo : getMap().getMapObjects()) {
if (mo.getType() == MapleMapObjectType.MONSTER) {
@@ -1316,12 +1317,16 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (map.isDojoMap()) { // spawns in dojo should be unlimited
useLimit = 0;
}
} else if (useSkillid >= 143 && useSkillid <= 145) {
if (this.isBuffed(MonsterStatus.WEAPON_REFLECT) || this.isBuffed(MonsterStatus.MAGIC_REFLECT)) {
return false;
}
}
if (useLimit > 0) {
monsterLock.lock();
try {
Integer times = this.skillsUsed.get(new Pair<>(toUse.getSkillId(), toUse.getSkillLevel()));
Integer times = this.skillsUsed.get(new Pair<>(useSkillid, toUse.getSkillLevel()));
if (times != null && times >= useLimit) {
return false;
}
@@ -1334,7 +1339,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
try {
/*
for (Pair<Integer, Integer> skill : usedSkills) {
if (skill.getLeft() == toUse.getSkillId() && skill.getRight() == toUse.getSkillLevel()) {
if (skill.getLeft() == useSkillid && skill.getRight() == toUse.getSkillLevel()) {
return false;
}
}
+8 -8
View File
@@ -214,20 +214,20 @@ public class MobSkill {
}
break;
case 143: // Weapon Reflect
stats.put(MonsterStatus.WEAPON_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.WEAPON_IMMUNITY, Integer.valueOf(x));
stats.put(MonsterStatus.WEAPON_REFLECT, 10);
stats.put(MonsterStatus.WEAPON_IMMUNITY, 10);
reflection.add(x);
break;
case 144: // Magic Reflect
stats.put(MonsterStatus.MAGIC_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_IMMUNITY, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_REFLECT, 10);
stats.put(MonsterStatus.MAGIC_IMMUNITY, 10);
reflection.add(x);
break;
case 145: // Weapon / Magic reflect
stats.put(MonsterStatus.WEAPON_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.WEAPON_IMMUNITY, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_IMMUNITY, Integer.valueOf(x));
stats.put(MonsterStatus.WEAPON_REFLECT, 10);
stats.put(MonsterStatus.WEAPON_IMMUNITY, 10);
stats.put(MonsterStatus.MAGIC_REFLECT, 10);
stats.put(MonsterStatus.MAGIC_IMMUNITY, 10);
reflection.add(x);
break;
case 154: // accuracy up
+16 -3
View File
@@ -35,15 +35,28 @@ import server.quest.MapleQuest;
public class MapleLootManager {
private static boolean isRelevantDrop(MonsterDropEntry dropEntry, List<MapleCharacter> partyMembers, List<MapleLootInventory> partyInv) {
int qStartAmount = 0, qCompleteAmount = 0;
MapleQuest quest = MapleQuest.getInstance(dropEntry.questid);
int qItemAmount = quest != null ? quest.getItemAmountNeeded(dropEntry.itemId) : 0;
if (quest != null) {
qStartAmount = quest.getStartItemAmountNeeded(dropEntry.itemId);
qCompleteAmount = quest.getCompleteItemAmountNeeded(dropEntry.itemId);
}
boolean restricted = MapleItemInformationProvider.getInstance().isLootRestricted(dropEntry.itemId);
boolean restricted = MapleItemInformationProvider.getInstance().isPickupRestricted(dropEntry.itemId);
for (int i = 0; i < partyMembers.size(); i++) {
MapleLootInventory chrInv = partyInv.get(i);
if (dropEntry.questid > 0) {
if (partyMembers.get(i).getQuestStatus(dropEntry.questid) != 1) {
int qItemAmount, chrQuestStatus = partyMembers.get(i).getQuestStatus(dropEntry.questid);
if (chrQuestStatus == 0) {
qItemAmount = qStartAmount;
} else if (chrQuestStatus != 1) {
continue;
} else {
qItemAmount = qCompleteAmount;
}
if (qItemAmount <= 0) {
continue;
}
+10 -1
View File
@@ -371,7 +371,16 @@ public class MapleQuest {
return relevantMobs;
}
public int getItemAmountNeeded(int itemid) {
public int getStartItemAmountNeeded(int itemid) {
MapleQuestRequirement req = startReqs.get(MapleQuestRequirementType.ITEM);
if(req == null)
return 0;
ItemRequirement ireq = (ItemRequirement) req;
return ireq.getItemAmountNeeded(itemid);
}
public int getCompleteItemAmountNeeded(int itemid) {
MapleQuestRequirement req = completeReqs.get(MapleQuestRequirementType.ITEM);
if(req == null)
return 0;
@@ -97,7 +97,7 @@ public class ItemRequirement extends MapleQuestRequirement {
}
public int getItemAmountNeeded(int itemid) {
if(items.containsKey(itemid)) {
if(items.containsKey(itemid)) {
return items.get(itemid);
}
+2 -2
View File
@@ -1065,7 +1065,7 @@ public class MaplePacketCreator {
mplew.writeShort(chr.getHp());
mplew.writeBool(false);
mplew.writeLong(getTime(Server.getInstance().getCurrentTime()));
mplew.skip(5);
mplew.skip(8);
return mplew.getPacket();
}
@@ -1082,7 +1082,7 @@ public class MaplePacketCreator {
mplew.writeInt(spawnPosition.x); // spawn position placement thanks to Arnah (Vertisy)
mplew.writeInt(spawnPosition.y);
mplew.writeLong(getTime(Server.getInstance().getCurrentTime()));
mplew.skip(5);
mplew.skip(8);
return mplew.getPacket();
}