Savior Commit

Fixed some bugs regarding dojo, updated drop data, minor tweaks on
Mystic Doors, added expeditions for Showa Manor, Zakum and Pink Bean,
smart search for item slots on quest/npc rewarding system, attempt on
boss HPbar to focus on player's current target, quests with selectable
rewards now hands the item correctly, after the first PQ instance next
ones are loaded more smoothly.
This commit is contained in:
ronancpl
2017-08-04 00:04:46 -03:00
parent c09bc02c85
commit 0a2e382c3b
968 changed files with 25555 additions and 7362 deletions

View File

@@ -227,7 +227,7 @@ public class MapleInventoryManipulator {
}
return true;
}
public static boolean checkSpace(MapleClient c, int itemid, int quantity, String owner) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ii.getInventoryType(itemid);
@@ -263,6 +263,52 @@ public class MapleInventoryManipulator {
}
}
public static int checkSpaceProgressively(MapleClient c, int itemid, int quantity, String owner, int usedSlots) {
// return value --> bit0: if has space for this one;
// value after: new slots filled;
int returnValue;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ii.getInventoryType(itemid);
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemid);
if (!ItemConstants.isRechargable(itemid)) {
List<Item> existing = c.getPlayer().getInventory(type).listById(itemid);
if (existing.size() > 0) // first update all existing slots to slotMax
{
for (Item eItem : existing) {
short oldQ = eItem.getQuantity();
if (oldQ < slotMax && owner.equals(eItem.getOwner())) {
short newQ = (short) Math.min(oldQ + quantity, slotMax);
quantity -= (newQ - oldQ);
}
if (quantity <= 0) {
break;
}
}
}
}
final int numSlotsNeeded;
if (slotMax > 0) {
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
} else if (ItemConstants.isRechargable(itemid)) {
numSlotsNeeded = 1;
} else {
numSlotsNeeded = 1;
}
returnValue = ((numSlotsNeeded + usedSlots) << 1);
returnValue += (numSlotsNeeded == 0 || !c.getPlayer().getInventory(type).isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0;
} else {
returnValue = ((1 + usedSlots) << 1);
returnValue += (!c.getPlayer().getInventory(type).isFullAfterSomeItems(0, usedSlots)) ? 1 : 0;
}
return returnValue;
}
public static void removeFromSlot(MapleClient c, MapleInventoryType type, short slot, short quantity, boolean fromDrop) {
removeFromSlot(c, type, slot, quantity, fromDrop, false);
}

View File

@@ -116,12 +116,15 @@ import constants.skills.WindArcher;
/**
* @author Matze
* @author Frz
* @author Ronan
*/
public class MapleStatEffect {
private short watk, matk, wdef, mdef, acc, avoid, speed, jump;
private short hp, mp;
private double hpR, mpR;
private short mhpRRate, mmpRRate;
private byte mhpR, mmpR;
private short mpCon, hpCon;
private int duration;
private boolean overTime, repeatEffect;
@@ -224,37 +227,48 @@ public class MapleStatEffect {
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.PYRAMID_PQ, Integer.valueOf(ret.berserk));
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.BOOSTER, Integer.valueOf(ret.booster));
if(MapleItemInformationProvider.getInstance().isRateCoupon(sourceid)) {
switch(MapleDataTool.getInt("expR", source, 0)) {
case 1:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP1, 1);
break;
case 2:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP2, 1);
break;
case 3:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP3, 1);
break;
case 4:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP4, 1);
break;
}
switch(MapleDataTool.getInt("drpR", source, 0)) {
case 1:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP1, 1);
break;
case 2:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP2, 1);
break;
case 3:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP3, 1);
break;
if(!skill) {
if(isDojoBuff(sourceid)) {
ret.mhpR = (byte) MapleDataTool.getInt("mhpR", source, 0);
ret.mhpRRate = (short) (MapleDataTool.getInt("mhpRRate", source, 0) * 100);
ret.mmpR = (byte) MapleDataTool.getInt("mmpRRate", source, 0);
ret.mmpRRate = (short) (MapleDataTool.getInt("mmpRRate", source, 0) * 100);
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.HPREC, Integer.valueOf(ret.mhpR));
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MPREC, Integer.valueOf(ret.mmpR));
} else if(isRateCoupon(sourceid)) {
switch(MapleDataTool.getInt("expR", source, 0)) {
case 1:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP1, 1);
break;
case 2:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP2, 1);
break;
case 3:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP3, 1);
break;
case 4:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP4, 1);
break;
}
switch(MapleDataTool.getInt("drpR", source, 0)) {
case 1:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP1, 1);
break;
case 2:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP2, 1);
break;
case 3:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP3, 1);
break;
}
}
}
}
@@ -819,7 +833,8 @@ public class MapleStatEffect {
SummonMovementType summonMovementType = getSummonMovementType();
if (overTime || isCygnusFA() || summonMovementType != null) {
if (summonMovementType != null && pos != null) {
applyto.cancelBuffStats(MapleBuffStat.SUMMON); // if player has a summon already, drop it
if(summonMovementType.getValue() == summonMovementType.STATIONARY.getValue()) applyto.cancelBuffStats(MapleBuffStat.PUPPET);
else applyto.cancelBuffStats(MapleBuffStat.SUMMON);
}
applyBuffEffect(applyfrom, applyto, primary);
@@ -854,7 +869,7 @@ public class MapleStatEffect {
Point doorPosition = new Point(applyto.getPosition().x, y);
MapleDoor door = new MapleDoor(applyto, doorPosition);
if(door.getOwnerId() > -1) {
if(door.getOwnerId() >= 0) {
if (applyto.getParty() != null) {
for (MaplePartyCharacter partyMember : applyto.getParty().getMembers()) {
partyMember.getPlayer().addDoor(door.getOwnerId(), door);
@@ -867,13 +882,17 @@ public class MapleStatEffect {
door.getTarget().spawnDoor(door.getAreaDoor());
door.getTown().spawnDoor(door.getTownDoor());
applyto.disableDoor();
} else {
if(door.getOwnerId() == -1) applyto.dropMessage(5, "There are no door portals available for the town at this moment. Try again later.");
else applyto.dropMessage(5, "Mystic Door cannot be cast on a slope, try elsewhere.");
MapleInventoryManipulator.addFromDrop(applyto.getClient(), new Item(4006000, (short) 0, (short) 1), false);
if(door.getOwnerId() == -3) applyto.dropMessage(5, "Mystic Door cannot be cast far from a spawn point. Nearest one is at " + door.getDoorStatus().getRight() + "pts " + door.getDoorStatus().getLeft());
else if(door.getOwnerId() == -2) applyto.dropMessage(5, "Mystic Door cannot be cast on a slope, try elsewhere.");
else applyto.dropMessage(5, "There are no door portals available for the town at this moment. Try again later.");
applyto.cancelBuffStats(MapleBuffStat.SOULARROW); // cancel door buff
}
applyto.disableDoor();
} else if (isMist()) {
Rectangle bounds = calculateBoundingBox(sourceid == NightWalker.POISON_BOMB ? pos : applyfrom.getPosition(), applyfrom.isFacingLeft());
MapleMist mist = new MapleMist(bounds, applyfrom, this);
@@ -1046,10 +1065,10 @@ public class MapleStatEffect {
}
if (isDash()) {
buff = MaplePacketCreator.givePirateBuff(statups, sourceid, seconds);
mbuff = MaplePacketCreator.giveForgeinPirateBuff(applyto.getId(), sourceid, seconds, localstatups);
mbuff = MaplePacketCreator.giveForeignPirateBuff(applyto.getId(), sourceid, seconds, localstatups);
} else if (isInfusion()) {
buff = MaplePacketCreator.givePirateBuff(localstatups, sourceid, seconds);
mbuff = MaplePacketCreator.giveForgeinPirateBuff(applyto.getId(), sourceid, seconds, localstatups);
mbuff = MaplePacketCreator.giveForeignPirateBuff(applyto.getId(), sourceid, seconds, localstatups);
} else if (isDs()) {
List<Pair<MapleBuffStat, Integer>> dsstat = Collections.singletonList(new Pair<>(MapleBuffStat.DARKSIGHT, 0));
mbuff = MaplePacketCreator.giveForeignBuff(applyto.getId(), dsstat);
@@ -1277,6 +1296,19 @@ public class MapleStatEffect {
public boolean isRecovery() {
return sourceid == Beginner.RECOVERY || sourceid == Noblesse.RECOVERY || sourceid == Legend.RECOVERY || sourceid == Evan.RECOVERY;
}
public boolean isDojoBuff() {
return sourceid >= 2022359 && sourceid <= 2022421;
}
public static boolean isDojoBuff(int sourceid) {
return sourceid >= 2022359 && sourceid <= 2022421;
}
public static boolean isRateCoupon(int sourceid) {
int itemType = sourceid / 1000;
return itemType == 5211 || itemType == 5360;
}
private boolean isDs() {
return skill && (sourceid == Rogue.DARK_SIGHT || sourceid == WindArcher.WIND_WALK || sourceid == NightWalker.DARK_SIGHT);
@@ -1303,7 +1335,7 @@ public class MapleStatEffect {
}
private boolean isCouponBuff() {
return MapleItemInformationProvider.getInstance().isRateCoupon(sourceid);
return isRateCoupon(sourceid);
}
private boolean isMysticDoor() {
@@ -1499,6 +1531,22 @@ public class MapleStatEffect {
public short getMp() {
return mp;
}
public byte getHpR() {
return mhpR;
}
public byte getMpR() {
return mmpR;
}
public short getHpRRate() {
return mhpRRate;
}
public short getMpRRate() {
return mmpRRate;
}
public short getHpCon() {
return hpCon;

View File

@@ -63,7 +63,7 @@ public final class MapleOxQuiz {
public void sendQuestion() {
int gm = 0;
for (MapleCharacter mc : map.getCharacters()) {
if (mc.gmLevel() > 0) {
if (mc.gmLevel() > 1) {
gm++;
}
}

View File

@@ -96,7 +96,7 @@ public class MapleExpedition {
private void beginRegistration() {
registering = true;
leader.announce(MaplePacketCreator.getClock(type.getRegistrationTime() * 60));
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, leader.getName() + " has been declared the expedition captain. Please register for the expedition."));
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "[Expedition] " + leader.getName() + " has been declared the expedition captain. Please register for the expedition."));
scheduleRegistrationEnd();
}
@@ -109,7 +109,7 @@ public class MapleExpedition {
public void run() {
if (registering){
leader.getClient().getChannelServer().getExpeditions().remove(exped);
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "Time limit has been reached. Expedition has been disbanded."));
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "[Expedition] The time limit has been reached. Expedition has been disbanded."));
dispose(false);
}
@@ -131,9 +131,9 @@ public class MapleExpedition {
public void start(){
registering = false;
broadcastExped(MaplePacketCreator.removeClock());
broadcastExped(MaplePacketCreator.serverNotice(6, "The expedition has started! Good luck, brave heroes!"));
broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] The expedition has started! Good luck, brave heroes!"));
startTime = System.currentTimeMillis();
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(6, type.toString() + " Expedition started with leader: " + leader.getName()));
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[Expedition] " + type.toString() + " Expedition started with leader: " + leader.getName()));
}
public String addMember(MapleCharacter player) {
@@ -148,7 +148,7 @@ public class MapleExpedition {
}
if (members.add(player)){
player.announce(MaplePacketCreator.getClock((int)(startTime - System.currentTimeMillis()) / 1000));
broadcastExped(MaplePacketCreator.serverNotice(6, player.getName() + " has joined the expedition!"));
broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
return "You have registered for the expedition successfully!";
}
return "Sorry, something went really wrong. Report this on the forum with a screenshot!";
@@ -163,8 +163,8 @@ public class MapleExpedition {
public boolean removeMember(MapleCharacter chr) {
if(members.remove(chr)) {
chr.announce(MaplePacketCreator.removeClock());
broadcastExped(MaplePacketCreator.serverNotice(6, chr.getName() + " has left the expedition."));
chr.dropMessage(6, "You have left this expedition.");
broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + chr.getName() + " has left the expedition."));
chr.dropMessage(6, "[Expedition] You have left this expedition.");
return true;
}
@@ -213,10 +213,10 @@ public class MapleExpedition {
banned.add(player.getId());
members.remove(player);
broadcastExped(MaplePacketCreator.serverNotice(6, player.getName() + " has been banned from the expedition."));
broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has been banned from the expedition."));
player.announce(MaplePacketCreator.removeClock());
player.dropMessage(6, "You have been banned from this expedition.");
player.dropMessage(6, "[Expedition] You have been banned from this expedition.");
}
}

View File

@@ -31,9 +31,10 @@ public enum MapleExpeditionType {
BALROG_EASY(3, 30, 50, 255, 5),
BALROG_NORMAL(6, 30, 50, 255, 5),
SCARGA(3, 6, 100, 255, 5),
SCARGA(6, 30, 100, 255, 5),
SHOWA(3, 30, 100, 255, 5),
ZAKUM(6, 30, 50, 255, 5),
HORNTAIL(6, 30, 80, 255,5),
HORNTAIL(6, 30, 100, 255, 5),
CHAOS_ZAKUM(6, 30, 120, 255, 5),
CHAOS_HORNTAIL(6, 30, 120, 255, 5),
PINKBEAN(6, 30, 120, 255, 5),

View File

@@ -179,7 +179,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
public boolean isBoss() {
return stats.isBoss() || isHT();
return stats.isBoss();
}
public int getAnimationTime(String name) {
@@ -209,18 +209,19 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
int trueDamage = Math.min(hp, damage); // since magic happens otherwise B^)
if(ServerConstants.USE_DEBUG == true && from != null) from.dropMessage(5, "Hitted MOB " + this.getId() + ", OID " + this.getObjectId());
if(ServerConstants.USE_DEBUG == true) from.dropMessage(5, "Hitted MOB " + this.getId() + ", OID " + this.getObjectId());
dispatchMonsterDamaged(from, trueDamage);
hp -= damage;
if (takenDamage.containsKey(from.getId())) {
takenDamage.get(from.getId()).addAndGet(trueDamage);
} else {
hp -= trueDamage;
if (!takenDamage.containsKey(from.getId())) {
takenDamage.put(from.getId(), new AtomicInteger(trueDamage));
} else {
takenDamage.get(from.getId()).addAndGet(trueDamage);
}
if (hasBossHPBar()) {
from.getMap().broadcastMessage(makeBossHPBarPacket(), getPosition());
from.setPlayerAggro(this.hashCode());
from.getMap().broadcastBossHpMessage(this, this.hashCode(), makeBossHPBarPacket(), getPosition());
} else if (!isBoss()) {
int remainingHP = (int) Math.max(1, hp * 100f / getMaxHp());
byte[] packet = MaplePacketCreator.showMonsterHP(getObjectId(), remainingHP);
@@ -531,11 +532,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
public boolean hasBossHPBar() {
return (isBoss() && getTagColor() > 0) || isHT();
}
private boolean isHT() {
return getId() == 8810018;
return isBoss() && getTagColor() > 0;
}
@Override
@@ -558,7 +555,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
this.getMap().killAllMonsters();
return;
}
c.announce(makeBossHPBarPacket());
c.announceBossHpBar(this, this.hashCode(), makeBossHPBarPacket());
}
}

View File

@@ -104,8 +104,8 @@ public class MobSkill {
public void applyEffect(MapleCharacter player, MapleMonster monster, boolean skill) {
MapleDisease disease = null;
Map<MonsterStatus, Integer> stats = new ArrayMap<MonsterStatus, Integer>();
List<Integer> reflection = new LinkedList<Integer>();
Map<MonsterStatus, Integer> stats = new ArrayMap<MonsterStatus, Integer>();
List<Integer> reflection = new LinkedList<Integer>();
switch (skillId) {
case 100:
case 110:
@@ -274,9 +274,9 @@ public class MobSkill {
}
}
break;
default:
System.out.println("Unhandled Mob skill: " + skillId);
break;
default:
System.out.println("Unhandled Mob skill: " + skillId);
break;
}
if (stats.size() > 0) {
if (lt != null && rb != null && skill) {

View File

@@ -22,11 +22,11 @@
package server.maps;
import java.awt.Point;
import java.util.Collections;
import java.util.List;
import tools.Pair;
import server.MaplePortal;
import client.MapleCharacter;
import constants.ServerConstants;
/**
*
@@ -38,6 +38,7 @@ public class MapleDoor {
private MapleMap town;
private MaplePortal townPortal;
private MapleMap target;
private Pair<String, Integer> posStatus = null;
private MapleDoorObject townDoor;
private MapleDoorObject areaDoor;
@@ -47,45 +48,39 @@ public class MapleDoor {
this.target = owner.getMap();
if(target.canDeployDoor(targetPosition)) {
this.town = this.target.getReturnMap();
this.townPortal = allocateFreePortal();
if(ServerConstants.USE_ENFORCE_MDOOR_POSITION) {
posStatus = target.getDoorPositionStatus(targetPosition);
}
if(posStatus == null) {
this.town = this.target.getReturnMap();
this.townPortal = getDoorPortal(owner.getDoorSlot());
if(townPortal != null) {
this.areaDoor = new MapleDoorObject(ownerId, town, target, false, targetPosition, townPortal.getPosition());
this.townDoor = new MapleDoorObject(ownerId, target, town, true, townPortal.getPosition(), targetPosition);
if(townPortal != null) {
this.areaDoor = new MapleDoorObject(ownerId, town, target, false, targetPosition, townPortal.getPosition());
this.townDoor = new MapleDoorObject(ownerId, target, town, true, townPortal.getPosition(), targetPosition);
this.areaDoor.setPairOid(this.townDoor.getObjectId());
this.townDoor.setPairOid(this.areaDoor.getObjectId());
this.areaDoor.setPairOid(this.townDoor.getObjectId());
this.townDoor.setPairOid(this.areaDoor.getObjectId());
} else {
this.ownerId = -1;
}
} else {
this.ownerId = -1;
this.ownerId = -3;
}
} else {
this.ownerId = -2;
}
}
public void freeAllocatedPortal() {
if(townPortal != null) {
town.setDisposeDoorPortal(townPortal);
private MaplePortal getDoorPortal(int slot) {
try {
return town.getAvailableDoorPortals().get(slot);
} catch (IndexOutOfBoundsException e) {
return town.getAvailableDoorPortals().get(0);
}
}
private MaplePortal allocateFreePortal() {
List<MaplePortal> availablePortals = town.getAvailableDoorPortals();
if(availablePortals.isEmpty() || !town.getNotUsingDoorPortal()) return null;
Collections.shuffle(availablePortals);
while(!availablePortals.isEmpty()) {
MaplePortal port = availablePortals.remove(0);
if(town.setUsingDoorPortal(port)) {
return port;
}
}
return null;
}
public int getOwnerId() {
return ownerId;
}
@@ -110,4 +105,7 @@ public class MapleDoor {
return target;
}
public Pair<String, Integer> getDoorStatus() {
return posStatus;
}
}

View File

@@ -51,9 +51,10 @@ public class MapleDoorObject extends AbstractMapleMapObject {
toPos = toPosition;
}
public void warp(MapleCharacter chr, boolean toTown) {
public void warp(final MapleCharacter chr, boolean toTown) {
if (chr.getId() == ownerId || (chr.getParty() != null && chr.getParty().getMemberById(ownerId) != null)) {
chr.changeMap(to, toPos);
if(chr.getParty() == null && (to.isLastDoorOwner(chr.getId()) || toTown)) chr.changeMap(to, toPos);
else chr.changeMap(to, to.findClosestPlayerSpawnpoint(toPos)); // weird issues happens with party, relocating players elsewhere....
} else {
chr.getClient().announce(MaplePacketCreator.blockedMessage(6));
chr.getClient().announce(MaplePacketCreator.enableActions());
@@ -63,13 +64,12 @@ public class MapleDoorObject extends AbstractMapleMapObject {
@Override
public void sendSpawnData(MapleClient client) {
if (from.getId() == client.getPlayer().getMapId()) {
client.announce(MaplePacketCreator.spawnPortal(this.getFrom().getId(), this.getTo().getId(), this.toPosition()));
if(!this.inTown()) client.announce(MaplePacketCreator.spawnDoor(this.getOwnerId(), this.getPosition(), true));
if (client.getPlayer().getParty() != null && (ownerId == client.getPlayer().getId() || client.getPlayer().getParty().getMemberById(ownerId) != null)) {
client.announce(MaplePacketCreator.partyPortal(this.getTown().getId(), this.getArea().getId(), this.getAreaPosition()));
client.announce(MaplePacketCreator.partyPortal(this.getFrom().getId(), this.getTo().getId(), this.toPosition()));
}
client.announce(MaplePacketCreator.spawnPortal(this.getFrom().getId(), this.getTo().getId(), this.toPosition()));
if(!this.inTown()) client.announce(MaplePacketCreator.spawnDoor(this.getOwnerId(), this.getPosition(), true));
}
}

View File

@@ -45,8 +45,6 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -95,8 +93,7 @@ public class MapleMap {
private Collection<MapleCharacter> characters = new LinkedHashSet<>();
private Map<Integer, MaplePortal> portals = new HashMap<>();
private Map<Integer, Integer> backgroundTypes = new HashMap<>();
private Map<String, Integer> environment = new LinkedHashMap<String, Integer>();
private Set<Integer> usedDoors = new HashSet<>();
private Map<String, Integer> environment = new LinkedHashMap<>();
private List<Rectangle> areas = new ArrayList<>();
private MapleFootholdTree footholds = null;
private int mapid;
@@ -129,6 +126,7 @@ public class MapleMap {
private Pair<Integer, String> timeMob = null;
private short mobInterval = 5000;
private boolean allowSummons = true; // All maps should have this true at the beginning
private int lastDoorOwner = -1;
// HPQ
private int riceCakes = 0;
private int bunnyDamage = 0;
@@ -186,7 +184,7 @@ public class MapleMap {
chrRLock.lock();
try {
for (MapleCharacter chr : characters) {
if (chr != source && (chr.gmLevel() > source.gmLevel())) {
if (chr != source && (chr.gmLevel() >= source.gmLevel())) {
chr.getClient().announce(packet);
}
}
@@ -200,7 +198,7 @@ public class MapleMap {
}
private double getRangedDistance() {
private static double getRangedDistance() {
return(ServerConstants.USE_MAXRANGE ? Double.POSITIVE_INFINITY : 722500);
}
@@ -354,8 +352,8 @@ public class MapleMap {
}
}
} finally {
chrRLock.unlock();
objectWLock.unlock();
chrRLock.unlock();
}
}
@@ -436,7 +434,56 @@ public class MapleMap {
public boolean canDeployDoor(Point pos) {
Point toStep = calcPointBelow(pos);
return toStep != null && toStep.distance(pos) < 20;
return toStep != null && toStep.distance(pos) <= 42;
}
/**
* Fetches angle relative between spawn and door points
* where 3 O'Clock is 0 and 12 O'Clock is 270 degrees
*
* @param spawnPoint
* @param doorPoint
* @return angle in degress from 0-360.
*/
private static double getAngle(Point doorPoint, Point spawnPoint) {
double dx = doorPoint.getX() - spawnPoint.getX();
// Minus to correct for coord re-mapping
double dy = -(doorPoint.getY() - spawnPoint.getY());
double inRads = Math.atan2(dy, dx);
// We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12 O'clock
if (inRads < 0)
inRads = Math.abs(inRads);
else
inRads = 2 * Math.PI - inRads;
return Math.toDegrees(inRads);
}
/**
* Converts angle in degrees to rounded cardinal coordinate.
*
* @param angle
* @return correspondent coordinate.
*/
public static String getRoundedCoordinate(double angle) {
String directions[] = {"E", "SE", "S", "SW", "W", "NW", "N", "NE", "E"};
return directions[ (int)Math.round(( ((double)angle % 360) / 45)) ];
}
public Pair<String, Integer> getDoorPositionStatus(Point pos) {
MaplePortal portal = findClosestPlayerSpawnpoint(pos);
double angle = getAngle(portal.getPosition(), pos);
double distn = pos.distanceSq(portal.getPosition());
if(distn <= 777777.7) {
return null;
}
distn = Math.sqrt(distn);
return new Pair(getRoundedCoordinate(angle), Integer.valueOf((int)distn));
}
private void dropFromMonster(final MapleCharacter chr, final MapleMonster mob) {
@@ -563,10 +610,14 @@ public class MapleMap {
}
public int countMonster(int id) {
return countMonster(id, id);
}
public int countMonster(int minid, int maxid) {
int count = 0;
for (MapleMapObject m : getMapObjectsInRange(new Point(0, 0), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.MONSTER))) {
MapleMonster mob = (MapleMonster) m;
if (mob.getId() == id) {
if (mob.getId() >= minid && mob.getId() <= maxid) {
count++;
}
}
@@ -726,7 +777,23 @@ public class MapleMap {
public void broadcastHorntailVictory() {
for (Channel cserv : Server.getInstance().getWorld(world).getChannels()) {
for (MapleCharacter player : cserv.getPlayerStorage().getAllCharacters()) {
player.dropMessage("To the crew that have finally conquered Horned Tail after numerous attempts, I salute thee! You are the true heroes of Leafre!!");
player.dropMessage(6, "[VICTORY] To the crew that have finally conquered Horned Tail after numerous attempts, I salute thee! You are the true heroes of Leafre!!");
}
}
}
public void broadcastZakumVictory() {
for (Channel cserv : Server.getInstance().getWorld(world).getChannels()) {
for (MapleCharacter player : cserv.getPlayerStorage().getAllCharacters()) {
player.dropMessage(6, "[VICTORY] At last, the tree of evil that for so long overwhelmed Ossyria has fallen. To the crew that managed to finally conquer Zakum, after numerous attempts, victory! You are the true heroes of Ossyria!!");
}
}
}
public void broadcastPinkBeanVictory(int channel) {
for (Channel cserv : Server.getInstance().getWorld(world).getChannels()) {
for (MapleCharacter player : cserv.getPlayerStorage().getAllCharacters()) {
player.dropMessage(6, "[VICTORY] In a swift stroke of sorts, the crew that has attempted Pink Bean at channel " + channel + " has ultimately defeated it. The Temple of Time shines radiantly once again, the day finally coming back, as the crew that managed to finally conquer it returns victoriously from the battlefield!!");
}
}
}
@@ -814,6 +881,14 @@ public class MapleMap {
dropFromMonster(dropOwner, monster);
}
if (monster.hasBossHPBar()) {
for(MapleCharacter mc : this.getAllPlayers()) {
if(mc.getTargetHpBarHash() == monster.hashCode()) {
mc.resetPlayerAggro();
}
}
}
monster.dispatchMonsterKilled();
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
}
@@ -823,7 +898,9 @@ public class MapleMap {
}
public void killMonster(int monsId) {
for (MapleMapObject mmo : getMapObjects()) {
List<MapleMapObject> mmoL = new LinkedList(getMapObjects());
for (MapleMapObject mmo : mmoL) {
if (mmo instanceof MapleMonster) {
if (((MapleMonster) mmo).getId() == monsId) {
this.killMonster((MapleMonster) mmo, (MapleCharacter) getPlayers().get(0), false);
@@ -980,8 +1057,6 @@ public class MapleMap {
public final void shuffleReactors(List<Object> list) {
List<Point> points = new ArrayList<>();
List<MapleMapObject> listObjects = new ArrayList<>();
List<MapleMapObject> reactors = getReactors();
List<MapleMapObject> targets = new LinkedList<>();
objectRLock.lock();
@@ -990,7 +1065,7 @@ public class MapleMap {
if(obj instanceof MapleMapObject) {
MapleMapObject mmo = (MapleMapObject) obj;
if(mapobjects.containsValue(mmo)) {
if(mapobjects.containsValue(mmo) && mmo.getType() == MapleMapObjectType.REACTOR) {
listObjects.add(mmo);
}
}
@@ -1328,9 +1403,6 @@ public class MapleMap {
spos.y--;
monster.setPosition(spos);
if (mapid < 925020000 || mapid > 925030000) {
monster.disableDrops();
}
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
@@ -1338,7 +1410,7 @@ public class MapleMap {
}
});
if (monster.hasBossHPBar()) {
broadcastMessage(monster.makeBossHPBarPacket(), monster.getPosition());
broadcastBossHpMessage(monster, monster.hashCode(), monster.makeBossHPBarPacket(), monster.getPosition());
}
updateMonsterController(monster);
@@ -1393,12 +1465,12 @@ public class MapleMap {
@Override
public void sendPackets(MapleClient c) {
if (door.getFrom().getId() == c.getPlayer().getMapId()) {
if (c.getPlayer().getParty() != null && (door.getOwnerId() == c.getPlayer().getId() || c.getPlayer().getParty().getMemberById(door.getOwnerId()) != null)) {
c.announce(MaplePacketCreator.partyPortal(door.getFrom().getId(), door.getTo().getId(), door.toPosition()));
}
c.announce(MaplePacketCreator.spawnPortal(door.getFrom().getId(), door.getTo().getId(), door.toPosition()));
if(!door.inTown()) c.announce(MaplePacketCreator.spawnDoor(door.getOwnerId(), door.getPosition(), false));
if (c.getPlayer().getParty() != null && (door.getOwnerId() == c.getPlayer().getId() || c.getPlayer().getParty().getMemberById(door.getOwnerId()) != null)) {
c.announce(MaplePacketCreator.partyPortal(door.getTown().getId(), door.getArea().getId(), door.getAreaPosition()));
}
}
c.announce(MaplePacketCreator.enableActions());
@@ -1409,36 +1481,8 @@ public class MapleMap {
return chr.getMapId() == door.getFrom().getId();
}
});
}
public boolean setUsingDoorPortal(MaplePortal port) {
objectWLock.lock();
try {
if(usedDoors.contains(port.getId())) return false;
usedDoors.add(port.getId());
return true;
} finally {
objectWLock.unlock();
}
}
public void setDisposeDoorPortal(MaplePortal port) {
objectWLock.lock();
try {
usedDoors.remove(port.getId());
} finally {
objectWLock.unlock();
}
}
public boolean getNotUsingDoorPortal() {
objectRLock.lock();
try {
return usedDoors.isEmpty();
} finally {
objectRLock.unlock();
}
if(!door.inTown()) setLastDoorOwner(door.getOwnerId());
}
public List<MaplePortal> getAvailableDoorPortals() {
@@ -1447,7 +1491,7 @@ public class MapleMap {
List<MaplePortal> availablePortals = new ArrayList<>();
for (MaplePortal port : getPortals()) {
if (port.getType() == MaplePortal.DOOR_PORTAL && !usedDoors.contains(port.getId())) {
if (port.getType() == MaplePortal.DOOR_PORTAL) {
availablePortals.add(port);
}
}
@@ -1905,7 +1949,6 @@ public class MapleMap {
updateMonsterController(monster);
}
chr.leaveMap();
chr.cancelMapTimeLimitTask();
for (MapleSummon summon : new ArrayList<>(chr.getSummonsValues())) {
if (summon.isStationary()) {
@@ -1933,6 +1976,10 @@ public class MapleMap {
broadcastMessage(MaplePacketCreator.serverNotice(type, message));
}
public void broadcastBossHpMessage(MapleMonster mm, int bossHash, final byte[] packet) {
broadcastBossHpMessage(mm, bossHash, null, packet, Double.POSITIVE_INFINITY, null);
}
public void broadcastMessage(final byte[] packet) {
broadcastMessage(null, packet, Double.POSITIVE_INFINITY, null);
}
@@ -1973,6 +2020,10 @@ public class MapleMap {
public void broadcastMessage(final byte[] packet, Point rangedFrom) {
broadcastMessage(null, packet, getRangedDistance(), rangedFrom);
}
public void broadcastBossHpMessage(MapleMonster mm, int bossHash, final byte[] packet, Point rangedFrom) {
broadcastBossHpMessage(mm, bossHash, null, packet, getRangedDistance(), rangedFrom);
}
/**
* Always ranged from point. Does not repeat to source.
@@ -2003,6 +2054,25 @@ public class MapleMap {
chrRLock.unlock();
}
}
private void broadcastBossHpMessage(MapleMonster mm, int bossHash, MapleCharacter source, final byte[] packet, double rangeSq, Point rangedFrom) {
chrRLock.lock();
try {
for (MapleCharacter chr : characters) {
if (chr != source) {
if (rangeSq < Double.POSITIVE_INFINITY) {
if (rangedFrom.distanceSq(chr.getPosition()) <= rangeSq) {
chr.getClient().announceBossHpBar(mm, bossHash, packet);
}
} else {
chr.getClient().announceBossHpBar(mm, bossHash, packet);
}
}
}
} finally {
chrRLock.unlock();
}
}
private boolean isNonRangedType(MapleMapObjectType type) {
switch (type) {
@@ -2020,32 +2090,38 @@ public class MapleMap {
private void sendObjectPlacement(MapleClient mapleClient) {
MapleCharacter chr = mapleClient.getPlayer();
Collection<MapleMapObject> objects;
objectRLock.lock();
try {
for (MapleMapObject o : mapobjects.values()) {
if (o.getType() == MapleMapObjectType.SUMMON) {
MapleSummon summon = (MapleSummon) o;
if (summon.getOwner() == chr) {
if (chr.isSummonsEmpty() || !chr.containsSummon(summon)) {
objectWLock.lock();
try {
mapobjects.remove(o);
} finally {
objectWLock.unlock();
}
continue;
}
}
}
if (isNonRangedType(o.getType())) {
o.sendSpawnData(mapleClient);
} else if (o.getType() == MapleMapObjectType.MONSTER) {
updateMonsterController((MapleMonster) o);
}
}
objects = Collections.unmodifiableCollection(mapobjects.values());
} finally {
objectRLock.unlock();
}
for (MapleMapObject o : objects) {
if (o.getType() == MapleMapObjectType.SUMMON) {
MapleSummon summon = (MapleSummon) o;
if (summon.getOwner() == chr) {
if (chr.isSummonsEmpty() || !chr.containsSummon(summon)) {
objectWLock.lock();
try {
mapobjects.remove(o.getObjectId());
} finally {
objectWLock.unlock();
}
continue;
}
}
}
if (isNonRangedType(o.getType())) {
o.sendSpawnData(mapleClient);
} else if (o.getType() == MapleMapObjectType.MONSTER) {
updateMonsterController((MapleMonster) o);
}
}
if (chr != null) {
for (MapleMapObject o : getMapObjectsInRange(chr.getPosition(), getRangedDistance(), rangedMapobjectTypes)) {
if (o.getType() == MapleMapObjectType.REACTOR) {
@@ -2372,7 +2448,7 @@ public class MapleMap {
public void makeDisappearItemFromMap(MapleMapItem mapitem) {
if (mapitem != null && mapitem == getMapObject(mapitem.getObjectId())) {
mapitem.itemLock.lock();
mapitem.lockItem();
try {
if (mapitem.isPickedUp()) {
return;
@@ -2380,7 +2456,7 @@ public class MapleMap {
MapleMap.this.broadcastMessage(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 0, 0), mapitem.getPosition());
mapitem.setPickedUp(true);
} finally {
mapitem.itemLock.unlock();
mapitem.unlockItem();
MapleMap.this.removeMapObject(mapitem);
}
}
@@ -2417,7 +2493,7 @@ public class MapleMap {
reactor.lockReactor();
try {
if (reactor.getShouldCollect() == true && mapitem != null && mapitem == getMapObject(mapitem.getObjectId())) {
mapitem.itemLock.lock();
mapitem.lockItem();
try {
TimerManager tMan = TimerManager.getInstance();
if (mapitem.isPickedUp()) {
@@ -2445,7 +2521,7 @@ public class MapleMap {
}, reactor.getDelay());
}
} finally {
mapitem.itemLock.unlock();
mapitem.unlockItem();
}
}
} finally {
@@ -2927,14 +3003,14 @@ public class MapleMap {
resetReactors();
}
public void resetMapObjects() {
resetMapObjects(1, false);
}
public final void resetFully() {
resetMapObjects();
}
public void resetMapObjects() {
resetMapObjects(1, false);
}
public void resetPQ() {
resetPQ(1);
}
@@ -2960,10 +3036,22 @@ public class MapleMap {
this.setDocked(state);
}
public boolean isLastDoorOwner(int cid) {
return lastDoorOwner == cid;
}
public void setLastDoorOwner(int cid) {
lastDoorOwner = cid;
}
public boolean isDojoMap() {
return mapid >= 925020000 && mapid < 925040000;
}
public boolean isDojoFightMap() {
return isDojoMap() && (((mapid / 100) % 100) % 6) > 0;
}
public boolean isHorntailDefeated() { // all parts of dead horntail can be found here?
for(int i = 8810010; i <= 8810017; i++) {
if(getMonsterById(i) == null) return false;

View File

@@ -35,7 +35,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
protected byte type;
protected boolean pickedUp = false, playerDrop;
protected long dropTime;
public ReentrantLock itemLock = new ReentrantLock();
private ReentrantLock itemLock = new ReentrantLock();
public MapleMapItem(Item item, Point position, MapleMapObject dropper, MapleCharacter owner, byte type, boolean playerDrop) {
setPosition(position);
@@ -107,17 +107,25 @@ public class MapleMapItem extends AbstractMapleMapObject {
this.pickedUp = pickedUp;
}
public long getDropTime() {
return dropTime;
}
public void setDropTime(long time) {
this.dropTime = time;
}
public long getDropTime() {
return dropTime;
}
public void setDropTime(long time) {
this.dropTime = time;
}
public byte getDropType() {
return type;
}
public void lockItem() {
itemLock.lock();
}
public void unlockItem() {
itemLock.unlock();
}
@Override
public final MapleMapObjectType getType() {

View File

@@ -22,14 +22,15 @@
package server.quest.actions;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataTool;
import server.MapleInventoryManipulator;
@@ -73,12 +74,24 @@ public class ItemAction extends MapleQuestAction {
if (iEntry.getChildByPath("job") != null)
job = MapleDataTool.getInt(iEntry.getChildByPath("job"));
items.add(new ItemData(id, count, prop, job, gender));
items.add(new ItemData(Integer.parseInt(iEntry.getName()), id, count, prop, job, gender));
}
Collections.sort(items, new Comparator<ItemData>()
{
@Override
public int compare( ItemData o1, ItemData o2 )
{
return o1.map - o2.map;
}
});
}
@Override
public void run(MapleCharacter chr, Integer extSelection) {
List<Pair<Integer, Integer>> takeItem = new LinkedList<>();
List<Pair<Integer, Integer>> giveItem = new LinkedList<>();
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
int props = 0, rndProps = 0, accProps = 0;
for(ItemData item : items) {
@@ -110,69 +123,114 @@ public class ItemAction extends MapleQuestAction {
}
}
if(iEntry.getCount() < 0) { // Remove Items
MapleInventoryType type = ii.getInventoryType(iEntry.getId());
int quantity = iEntry.getCount() * -1; // Invert
if(type.equals(MapleInventoryType.EQUIP)) {
if(chr.getInventory(type).countById(iEntry.getId()) < quantity) {
// Not enough in the equip inventoty, so check Equipped...
if(chr.getInventory(MapleInventoryType.EQUIPPED).countById(iEntry.getId()) > quantity) {
// Found it equipped, so change the type to equipped.
type = MapleInventoryType.EQUIPPED;
}
}
}
MapleInventoryManipulator.removeById(chr.getClient(), type, iEntry.getId(), quantity, true, false);
chr.announce(MaplePacketCreator.getShowItemGain(iEntry.getId(), (short) iEntry.getCount(), true));
} else {
if (chr.getInventory(MapleItemInformationProvider.getInstance().getInventoryType(iEntry.getId())).getNextFreeSlot() > -1) {
MapleInventoryManipulator.addById(chr.getClient(), iEntry.getId(), (short) iEntry.getCount());
chr.announce(MaplePacketCreator.getShowItemGain(iEntry.getId(), (short) iEntry.getCount(), true));
} else {
chr.dropMessage(1, "Inventory Full");
}
if(iEntry.getCount() < 0) { // Remove Item
takeItem.add(new Pair<>(iEntry.getId(), iEntry.getCount()));
} else { // Give Item
giveItem.add(new Pair<>(iEntry.getId(), iEntry.getCount()));
}
}
// must take all needed items before giving others
for(Pair<Integer, Integer> iEntry: takeItem) {
MapleInventoryType type = ii.getInventoryType(iEntry.getLeft());
int quantity = iEntry.getRight() * -1; // Invert
if(type.equals(MapleInventoryType.EQUIP)) {
if(chr.getInventory(type).countById(iEntry.getLeft()) < quantity) {
// Not enough in the equip inventoty, so check Equipped...
if(chr.getInventory(MapleInventoryType.EQUIPPED).countById(iEntry.getLeft()) > quantity) {
// Found it equipped, so change the type to equipped.
type = MapleInventoryType.EQUIPPED;
}
}
}
MapleInventoryManipulator.removeById(chr.getClient(), type, iEntry.getLeft(), quantity, true, false);
chr.announce(MaplePacketCreator.getShowItemGain(iEntry.getLeft(), (short) iEntry.getRight().shortValue(), true));
}
for(Pair<Integer, Integer> iEntry: giveItem) {
MapleInventoryManipulator.addById(chr.getClient(), iEntry.getLeft(), (short) iEntry.getRight().shortValue());
chr.announce(MaplePacketCreator.getShowItemGain(iEntry.getLeft(), (short) iEntry.getRight().shortValue(), true));
}
}
@Override
public boolean check(MapleCharacter chr, Integer extSelection) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
EnumMap<MapleInventoryType, Integer> props = new EnumMap<>(MapleInventoryType.class);
List<Pair<Item, MapleInventoryType>> itemList = new ArrayList<>();
for(ItemData item : items) {
if (!canGetItem(item, chr)) {
List<Pair<Item, MapleInventoryType>> gainList = new LinkedList<>();
List<Pair<Item, MapleInventoryType>> selectList = new LinkedList<>();
List<Pair<Item, MapleInventoryType>> randomList = new LinkedList<>();
List<Integer> allSlotUsed = new ArrayList(5);
for(byte i = 0; i < 5; i++) allSlotUsed.add(0);
for(ItemData item : items) {
if (!canGetItem(item, chr)) {
continue;
}
MapleInventoryType type = ii.getInventoryType(item.getId());
if(item.getProp() != null) {
if(!props.containsKey(type)) {
props.put(type, item.getId());
}
continue;
}
if(item.getCount() > 0) {
// Make sure they can hold the item.
Item toItem = new Item(item.getId(), (short) 0, (short) item.getCount());
itemList.add(new Pair<>(toItem, type));
Item toItem = new Item(item.getId(), (short) 0, (short) item.getCount());
if(item.getProp() < 0) {
selectList.add(new Pair<>(toItem, type));
} else {
randomList.add(new Pair<>(toItem, type));
}
} else {
// Make sure they actually have the item.
int quantity = item.getCount() * -1;
if(chr.getInventory(type).countById(item.getId()) < quantity) {
if(type.equals(MapleInventoryType.EQUIP) && chr.getInventory(MapleInventoryType.EQUIPPED).countById(item.getId()) > quantity)
continue;
return false;
}
}
if(item.getCount() > 0) {
// Make sure they can hold the item.
Item toItem = new Item(item.getId(), (short) 0, (short) item.getCount());
gainList.add(new Pair<>(toItem, type));
} else {
// Make sure they actually have the item.
int quantity = item.getCount() * -1;
int freeSlotCount = chr.getInventory(type).freeSlotCountById(item.getId(), quantity);
if(freeSlotCount == -1) {
if(type.equals(MapleInventoryType.EQUIP) && chr.getInventory(MapleInventoryType.EQUIPPED).countById(item.getId()) > quantity)
continue;
chr.dropMessage(1, "Please check if you have enough items in your inventory.");
return false;
} else {
int idx = type.getType() - 1; // more slots available from the given items!
allSlotUsed.set(idx, allSlotUsed.get(idx) - freeSlotCount);
}
}
}
}
for(Integer itemID : props.values()) {
MapleInventoryType type = ii.getInventoryType(itemID);
Item toItem = new Item(itemID, (short) 0, (short) 1);
itemList.add(new Pair<>(toItem, type));
}
if (!MapleInventory.checkSpots(chr, itemList)) {
if(!randomList.isEmpty()) {
int result;
MapleClient c = chr.getClient();
List<Integer> rndUsed = new ArrayList(5);
for(byte i = 0; i < 5; i++) rndUsed.add(allSlotUsed.get(i));
for(Pair<Item, MapleInventoryType> it: randomList) {
int idx = it.getRight().getType() - 1;
result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getLeft().getItemId(), it.getLeft().getQuantity(), "", rndUsed.get(idx));
if(result % 2 == 0) {
chr.dropMessage(1, "Please check if you have enough space in your inventory.");
return false;
}
allSlotUsed.set(idx, Math.max(allSlotUsed.get(idx), result >> 1));
}
}
if(!selectList.isEmpty()) {
Pair<Item, MapleInventoryType> selected = selectList.get(extSelection);
gainList.add(selected);
}
if (!MapleInventory.checkSpots(chr, gainList, allSlotUsed)) {
chr.dropMessage(1, "Please check if you have enough space in your inventory.");
return false;
}
@@ -199,11 +257,12 @@ public class ItemAction extends MapleQuestAction {
}
private class ItemData {
private final int id, count, job, gender;
private final int map, id, count, job, gender;
private final Integer prop;
public ItemData(int id, int count, Integer prop, int job, int gender) {
this.id = id;
public ItemData(int map, int id, int count, Integer prop, int job, int gender) {
this.map = map;
this.id = id;
this.count = count;
this.prop = prop;
this.job = job;