Event Recall + Cash Shop bestsellers + MapleSessionCoordinator rework

Implemented an event recall system. Players that went disconnected during an event instance are able to rejoin the ongoing event upon relogin.
Implemented a player-activity backed best-sellers system for the Cash Shop.
Patched the recently added selective loot system interfering with quest items, ever disabling drops after the player picked up one item.
Implemented a server flag for everlasting buffs.
Fixed some inconsistencies with Priest Dispel skill, sometimes crashing party players.
Fixed change job not properly showing effects for other players.
Fixed wrong fee value being taken from players that expands their guild size. Also, implemented GMS-like fee for this action.
Reworked the MapleSessionCoordinator, now evaluating client's HWID as well as remote IP. This's expected to lessen account drought time for players that are constantly changing their IP.

Last but not least, added world maps for Mushroom Castle, Zipangu, CBD/Malaysia and Ellin Forest regions. Original artwork content used on files depicted in this topic are rightful property of Nexon Corps., these files thoroughly trying to adhere the "Fair Use" disclaimer policy, their purpose being solely to fulfill gaming experience for the areas that were already present on v83 GMS but still lacked worldmaps. For more info regarding Fair Use, please refer to "http://www.dmlp.org/legal-guide/fair-use".
This commit is contained in:
ronancpl
2018-09-07 14:55:29 -03:00
parent 132f286391
commit c3e3c6dfbb
83 changed files with 2718 additions and 626 deletions

View File

@@ -998,7 +998,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public FameStatus canGiveFame(MapleCharacter from) {
if (gmLevel > 0) {
if (this.isGM()) {
return FameStatus.OK;
} else if (lastfametime >= System.currentTimeMillis() - 3600000 * 24) {
return FameStatus.NOT_TODAY;
@@ -1171,9 +1171,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
setMasteries(this.job.getId());
guildUpdate();
getMap().broadcastMessage(this, MaplePacketCreator.removePlayerFromMap(this.getId()), false);
getMap().broadcastMessage(this, MaplePacketCreator.spawnPlayerMapObject(this), false);
getMap().broadcastMessage(this, MaplePacketCreator.showForeignEffect(getId(), 8), false);
getMap().broadcastMessage(this, MaplePacketCreator.showForeignEffect(this.getId(), 8), false);
if (GameConstants.hasSPTable(newJob) && newJob.getId() != 2001) {
if (getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
@@ -1182,8 +1180,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
createDragon();
}
if(ServerConstants.USE_ANNOUNCE_CHANGEJOB) {
if(gmLevel > 1) {
if (ServerConstants.USE_ANNOUNCE_CHANGEJOB) {
if (!this.isGM()) {
broadcastAcquaintances(6, "[" + GameConstants.ordinal(GameConstants.getJobBranch(newJob)) + " Job] " + name + " has just become a " + newJob.name() + ".");
}
}
@@ -2793,7 +2791,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public enum FameStatus {
OK, NOT_TODAY, NOT_THIS_MONTH
}
@@ -2887,9 +2884,39 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
private synchronized int applyFame(int delta) {
int newFame = fame + delta;
if (newFame < -30000) {
delta = -(30000 + fame);
} else if (newFame > 30000) {
delta = 30000 - fame;
}
fame += delta;
return delta;
}
public void gainFame(int delta) {
this.addFame(delta);
this.updateSingleStat(MapleStat.FAME, this.fame);
gainFame(delta, null, 0);
}
public boolean gainFame(int delta, MapleCharacter fromPlayer, int mode) {
delta = applyFame(delta);
if (delta != 0) {
int thisFame = fame;
updateSingleStat(MapleStat.FAME, thisFame);
if (fromPlayer != null) {
fromPlayer.announce(MaplePacketCreator.giveFameResponse(mode, getName(), thisFame));
announce(MaplePacketCreator.receiveFame(mode, fromPlayer.getName()));
} else {
announce(MaplePacketCreator.getShowFameGain(delta));
}
return true;
} else {
return false;
}
}
public void gainMeso(int gain) {
@@ -5417,16 +5444,18 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return getInventory(MapleInventoryType.getByType(invType)).getNextFreeSlot() > -1;
}
public void increaseGuildCapacity() { //hopefully nothing is null
if (getMeso() < MapleGuild.getIncreaseGuildCost(getGuild().getCapacity())) {
public void increaseGuildCapacity() {
int cost = MapleGuild.getIncreaseGuildCost(getGuild().getCapacity());
if (getMeso() < cost) {
dropMessage(1, "You don't have enough mesos.");
return;
}
if(Server.getInstance().increaseGuildCapacity(guildid)) {
gainMeso(-MapleGuild.getIncreaseGuildCost(getGuild().getCapacity()), true, false, false);
gainMeso(-cost, true, false, true);
} else {
dropMessage(1, "You guild already reached the maximum capacity of players.");
dropMessage(1, "Your guild already reached the maximum capacity of players.");
}
}
@@ -5581,155 +5610,160 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void levelUp(boolean takeexp) {
Skill improvingMaxHP = null;
Skill improvingMaxMP = null;
int improvingMaxHPLevel = 0;
int improvingMaxMPLevel = 0;
petLock.lock();
try {
Skill improvingMaxHP = null;
Skill improvingMaxMP = null;
int improvingMaxHPLevel = 0;
int improvingMaxMPLevel = 0;
boolean isBeginner = isBeginnerJob();
if (ServerConstants.USE_AUTOASSIGN_STARTERS_AP && isBeginner && level < 11) {
remainingAp = 0;
if (level < 6) {
str += 5;
} else {
str += 4;
dex += 1;
}
} else {
remainingAp += 5;
if (isCygnus() && level > 10 && level < 70) {
remainingAp++;
}
}
if (isBeginner) {
maxhp += Randomizer.rand(12, 16);
maxmp += Randomizer.rand(10, 12);
} else if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1)) {
improvingMaxHP = isCygnus() ? SkillFactory.getSkill(DawnWarrior.MAX_HP_INCREASE) : SkillFactory.getSkill(Swordsman.IMPROVED_MAX_HP_INCREASE);
if (job.isA(MapleJob.CRUSADER)) {
improvingMaxMP = SkillFactory.getSkill(1210000);
} else if (job.isA(MapleJob.DAWNWARRIOR2)) {
improvingMaxMP = SkillFactory.getSkill(11110000);
}
improvingMaxHPLevel = getSkillLevel(improvingMaxHP);
maxhp += Randomizer.rand(24, 28);
maxmp += Randomizer.rand(4, 6);
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
improvingMaxMP = isCygnus() ? SkillFactory.getSkill(BlazeWizard.INCREASING_MAX_MP) : SkillFactory.getSkill(Magician.IMPROVED_MAX_MP_INCREASE);
improvingMaxMPLevel = getSkillLevel(improvingMaxMP);
maxhp += Randomizer.rand(10, 14);
maxmp += Randomizer.rand(22, 24);
} else if (job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.THIEF) || (job.getId() > 1299 && job.getId() < 1500)) {
maxhp += Randomizer.rand(20, 24);
maxmp += Randomizer.rand(14, 16);
} else if (job.isA(MapleJob.GM)) {
maxhp = 30000;
maxmp = 30000;
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
improvingMaxHP = isCygnus() ? SkillFactory.getSkill(ThunderBreaker.IMPROVE_MAX_HP) : SkillFactory.getSkill(5100000);
improvingMaxHPLevel = getSkillLevel(improvingMaxHP);
maxhp += Randomizer.rand(22, 28);
maxmp += Randomizer.rand(18, 23);
} else if (job.isA(MapleJob.ARAN1)) {
maxhp += Randomizer.rand(44, 48);
int aids = Randomizer.rand(4, 8);
maxmp += aids + Math.floor(aids * 0.1);
}
if (improvingMaxHPLevel > 0 && (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.PIRATE) || job.isA(MapleJob.DAWNWARRIOR1))) {
maxhp += improvingMaxHP.getEffect(improvingMaxHPLevel).getX();
}
if (improvingMaxMPLevel > 0 && (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.CRUSADER) || job.isA(MapleJob.BLAZEWIZARD1))) {
maxmp += improvingMaxMP.getEffect(improvingMaxMPLevel).getX();
}
if (ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
maxmp += localint_ / 20;
} else {
maxmp += localint_ / 10;
}
}
if (takeexp) {
exp.addAndGet(-ExpTable.getExpNeededForLevel(level));
if (exp.get() < 0) {
exp.set(0);
}
}
level++;
if (level >= getMaxClassLevel()) {
exp.set(0);
level = getMaxClassLevel(); //To prevent levels past the maximum
}
maxhp = Math.min(30000, maxhp);
maxmp = Math.min(30000, maxmp);
if (level == 200) {
exp.set(0);
if(ServerConstants.PLAYERNPC_AUTODEPLOY && !this.isGM()) MaplePlayerNPC.spawnPlayerNPC(GameConstants.getHallOfFameMapid(job), this);
}
recalcLocalStats();
hp = localmaxhp;
mp = localmaxmp;
List<Pair<MapleStat, Integer>> statup = new ArrayList<>(10);
statup.add(new Pair<>(MapleStat.AVAILABLEAP, remainingAp));
statup.add(new Pair<>(MapleStat.HP, localmaxhp));
statup.add(new Pair<>(MapleStat.MP, localmaxmp));
statup.add(new Pair<>(MapleStat.EXP, exp.get()));
statup.add(new Pair<>(MapleStat.LEVEL, level));
statup.add(new Pair<>(MapleStat.MAXHP, maxhp));
statup.add(new Pair<>(MapleStat.MAXMP, maxmp));
statup.add(new Pair<>(MapleStat.STR, Math.min(str, Short.MAX_VALUE)));
statup.add(new Pair<>(MapleStat.DEX, Math.min(dex, Short.MAX_VALUE)));
if (job.getId() % 1000 > 0) {
remainingSp[GameConstants.getSkillBook(job.getId())] += 3;
statup.add(new Pair<>(MapleStat.AVAILABLESP, remainingSp[GameConstants.getSkillBook(job.getId())]));
}
client.announce(MaplePacketCreator.updatePlayerStats(statup, this));
getMap().broadcastMessage(this, MaplePacketCreator.showForeignEffect(getId(), 0), false);
recalcLocalStats();
setMPC(new MaplePartyCharacter(this));
silentPartyUpdate();
if(level == 10 && party != null) {
if(this.isPartyLeader()) party.assignNewLeader(client);
PartyOperationHandler.leaveParty(party, mpc, client);
showHint("You have reached #blevel 10#k, therefore you must leave your #rstarter party#k.");
}
if (this.guildid > 0) {
getGuild().broadcast(MaplePacketCreator.levelUpMessage(2, level, name), this.getId());
}
if (ServerConstants.USE_PERFECT_PITCH && level >= 30) {
//milestones?
if (MapleInventoryManipulator.checkSpace(client, 4310000, (short) 1, "")) {
MapleInventoryManipulator.addById(client, 4310000, (short) 1);
}
}
if (level == 200 && !isGM()) {
final String names = (getMedalText() + name);
client.getWorldServer().broadcastPacket(MaplePacketCreator.serverNotice(6, String.format(LEVEL_200, names, names)));
}
if(level % 20 == 0 && ServerConstants.USE_ADD_SLOTS_BY_LEVEL == true) {
if (!isGM()) {
for (byte i = 1; i < 5; i++) {
gainSlots(i, 4, true);
boolean isBeginner = isBeginnerJob();
if (ServerConstants.USE_AUTOASSIGN_STARTERS_AP && isBeginner && level < 11) {
remainingAp = 0;
if (level < 6) {
str += 5;
} else {
str += 4;
dex += 1;
}
this.yellowMessage("You reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
}
} else {
remainingAp += 5;
if (isCygnus() && level > 10 && level < 70) {
remainingAp++;
}
}
if (isBeginner) {
maxhp += Randomizer.rand(12, 16);
maxmp += Randomizer.rand(10, 12);
} else if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1)) {
improvingMaxHP = isCygnus() ? SkillFactory.getSkill(DawnWarrior.MAX_HP_INCREASE) : SkillFactory.getSkill(Swordsman.IMPROVED_MAX_HP_INCREASE);
if (job.isA(MapleJob.CRUSADER)) {
improvingMaxMP = SkillFactory.getSkill(1210000);
} else if (job.isA(MapleJob.DAWNWARRIOR2)) {
improvingMaxMP = SkillFactory.getSkill(11110000);
}
improvingMaxHPLevel = getSkillLevel(improvingMaxHP);
maxhp += Randomizer.rand(24, 28);
maxmp += Randomizer.rand(4, 6);
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
improvingMaxMP = isCygnus() ? SkillFactory.getSkill(BlazeWizard.INCREASING_MAX_MP) : SkillFactory.getSkill(Magician.IMPROVED_MAX_MP_INCREASE);
improvingMaxMPLevel = getSkillLevel(improvingMaxMP);
maxhp += Randomizer.rand(10, 14);
maxmp += Randomizer.rand(22, 24);
} else if (job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.THIEF) || (job.getId() > 1299 && job.getId() < 1500)) {
maxhp += Randomizer.rand(20, 24);
maxmp += Randomizer.rand(14, 16);
} else if (job.isA(MapleJob.GM)) {
maxhp = 30000;
maxmp = 30000;
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
improvingMaxHP = isCygnus() ? SkillFactory.getSkill(ThunderBreaker.IMPROVE_MAX_HP) : SkillFactory.getSkill(5100000);
improvingMaxHPLevel = getSkillLevel(improvingMaxHP);
maxhp += Randomizer.rand(22, 28);
maxmp += Randomizer.rand(18, 23);
} else if (job.isA(MapleJob.ARAN1)) {
maxhp += Randomizer.rand(44, 48);
int aids = Randomizer.rand(4, 8);
maxmp += aids + Math.floor(aids * 0.1);
}
if (improvingMaxHPLevel > 0 && (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.PIRATE) || job.isA(MapleJob.DAWNWARRIOR1))) {
maxhp += improvingMaxHP.getEffect(improvingMaxHPLevel).getX();
}
if (improvingMaxMPLevel > 0 && (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.CRUSADER) || job.isA(MapleJob.BLAZEWIZARD1))) {
maxmp += improvingMaxMP.getEffect(improvingMaxMPLevel).getX();
}
if (ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
maxmp += localint_ / 20;
} else {
maxmp += localint_ / 10;
}
}
if (takeexp) {
exp.addAndGet(-ExpTable.getExpNeededForLevel(level));
if (exp.get() < 0) {
exp.set(0);
}
}
level++;
if (level >= getMaxClassLevel()) {
exp.set(0);
level = getMaxClassLevel(); //To prevent levels past the maximum
}
maxhp = Math.min(30000, maxhp);
maxmp = Math.min(30000, maxmp);
if (level == 200) {
exp.set(0);
if(ServerConstants.PLAYERNPC_AUTODEPLOY && !this.isGM()) MaplePlayerNPC.spawnPlayerNPC(GameConstants.getHallOfFameMapid(job), this);
}
recalcLocalStats();
hp = localmaxhp;
mp = localmaxmp;
List<Pair<MapleStat, Integer>> statup = new ArrayList<>(10);
statup.add(new Pair<>(MapleStat.AVAILABLEAP, remainingAp));
statup.add(new Pair<>(MapleStat.HP, localmaxhp));
statup.add(new Pair<>(MapleStat.MP, localmaxmp));
statup.add(new Pair<>(MapleStat.EXP, exp.get()));
statup.add(new Pair<>(MapleStat.LEVEL, level));
statup.add(new Pair<>(MapleStat.MAXHP, maxhp));
statup.add(new Pair<>(MapleStat.MAXMP, maxmp));
statup.add(new Pair<>(MapleStat.STR, Math.min(str, Short.MAX_VALUE)));
statup.add(new Pair<>(MapleStat.DEX, Math.min(dex, Short.MAX_VALUE)));
if (job.getId() % 1000 > 0) {
remainingSp[GameConstants.getSkillBook(job.getId())] += 3;
statup.add(new Pair<>(MapleStat.AVAILABLESP, remainingSp[GameConstants.getSkillBook(job.getId())]));
}
client.announce(MaplePacketCreator.updatePlayerStats(statup, this));
getMap().broadcastMessage(this, MaplePacketCreator.showForeignEffect(getId(), 0), false);
recalcLocalStats();
setMPC(new MaplePartyCharacter(this));
silentPartyUpdate();
if(level == 10 && party != null) {
if(this.isPartyLeader()) party.assignNewLeader(client);
PartyOperationHandler.leaveParty(party, mpc, client);
showHint("You have reached #blevel 10#k, therefore you must leave your #rstarter party#k.");
}
if (this.guildid > 0) {
getGuild().broadcast(MaplePacketCreator.levelUpMessage(2, level, name), this.getId());
}
if (ServerConstants.USE_PERFECT_PITCH && level >= 30) {
//milestones?
if (MapleInventoryManipulator.checkSpace(client, 4310000, (short) 1, "")) {
MapleInventoryManipulator.addById(client, 4310000, (short) 1);
}
}
if (level == 200 && !isGM()) {
final String names = (getMedalText() + name);
client.getWorldServer().broadcastPacket(MaplePacketCreator.serverNotice(6, String.format(LEVEL_200, names, names)));
}
if(level % 20 == 0 && ServerConstants.USE_ADD_SLOTS_BY_LEVEL == true) {
if (!isGM()) {
for (byte i = 1; i < 5; i++) {
gainSlots(i, 4, true);
}
this.yellowMessage("You reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
}
}
if (level % 20 == 0 && ServerConstants.USE_ADD_RATES_BY_LEVEL == true) { //For the rate upgrade
revertLastPlayerRates();
setPlayerRates();
this.yellowMessage("You managed to get level " + level + "! Getting experience and items seems a little easier now, huh?");
}
levelUpMessages();
guildUpdate();
} finally {
petLock.unlock();
}
if (level % 20 == 0 && ServerConstants.USE_ADD_RATES_BY_LEVEL == true) { //For the rate upgrade
revertLastPlayerRates();
setPlayerRates();
this.yellowMessage("You managed to get level " + level + "! Getting experience and items seems a little easier now, huh?");
}
levelUpMessages();
guildUpdate();
}
public void gainAp(int amount) {
@@ -6939,27 +6973,25 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
visibleMapObjects.remove(mo);
}
public void resetStats() {
public synchronized void resetStats() {
if(!ServerConstants.USE_AUTOASSIGN_STARTERS_AP) {
return;
}
List<Pair<MapleStat, Integer>> statup = new ArrayList<>(5);
int tap = 0, tsp = 1;
int tap = remainingAp + str + dex + int_ + luk, tsp = 1;
int tstr = 4, tdex = 4, tint = 4, tluk = 4;
int levelap = (isCygnus() ? 6 : 5);
switch (job.getId()) {
case 100:
case 1100:
case 2100:
tstr = 35;
tap = ((getLevel() - 10) * levelap) + 14;
tsp += ((getLevel() - 10) * 3);
break;
case 200:
case 1200:
tint = 20;
tap = ((getLevel() - 8) * levelap) + 29;
tsp += ((getLevel() - 8) * 3);
break;
case 300:
@@ -6967,29 +6999,37 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
case 400:
case 1400:
tdex = 25;
tap = ((getLevel() - 10) * levelap) + 24;
tsp += ((getLevel() - 10) * 3);
break;
case 500:
case 1500:
tdex = 20;
tap = ((getLevel() - 10) * levelap) + 29;
tsp += ((getLevel() - 10) * 3);
break;
}
this.remainingAp = tap;
this.remainingSp[GameConstants.getSkillBook(job.getId())] = tsp;
this.dex = tdex;
this.int_ = tint;
this.str = tstr;
this.luk = tluk;
statup.add(new Pair<>(MapleStat.AVAILABLEAP, tap));
statup.add(new Pair<>(MapleStat.AVAILABLESP, tsp));
statup.add(new Pair<>(MapleStat.STR, tstr));
statup.add(new Pair<>(MapleStat.DEX, tdex));
statup.add(new Pair<>(MapleStat.INT, tint));
statup.add(new Pair<>(MapleStat.LUK, tluk));
announce(MaplePacketCreator.updatePlayerStats(statup, this));
tap -= tstr;
tap -= tdex;
tap -= tint;
tap -= tluk;
if (tap >= 0) {
this.remainingAp = tap;
this.remainingSp[GameConstants.getSkillBook(job.getId())] = tsp;
this.str = tstr;
this.dex = tdex;
this.int_ = tint;
this.luk = tluk;
statup.add(new Pair<>(MapleStat.AVAILABLEAP, tap));
statup.add(new Pair<>(MapleStat.AVAILABLESP, tsp));
statup.add(new Pair<>(MapleStat.STR, tstr));
statup.add(new Pair<>(MapleStat.DEX, tdex));
statup.add(new Pair<>(MapleStat.INT, tint));
statup.add(new Pair<>(MapleStat.LUK, tluk));
announce(MaplePacketCreator.updatePlayerStats(statup, this));
} else {
FilePrinter.print(FilePrinter.EXCEPTION_CAUGHT, name + " tried to get their stats reseted, without having enough AP available.");
}
}
public void resetBattleshipHp() {
@@ -8474,18 +8514,20 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
announce(MaplePacketCreator.updateQuestInfo((short) qs.getQuest().getId(), qs.getNpc()));
}
private void fameGainByQuest() {
public void awardQuestPoint(int awardedPoints) {
if (ServerConstants.QUEST_POINT_REQUIREMENT < 1 || awardedPoints < 1) return;
int delta;
synchronized (quests) {
quest_fame += 1;
quest_fame += awardedPoints;
int delta = quest_fame / ServerConstants.FAME_GAIN_BY_QUEST;
if(delta > 0) {
gainFame(delta);
client.announce(MaplePacketCreator.getShowFameGain(delta));
}
quest_fame %= ServerConstants.FAME_GAIN_BY_QUEST;
delta = quest_fame / ServerConstants.QUEST_POINT_REQUIREMENT;
quest_fame %= ServerConstants.QUEST_POINT_REQUIREMENT;
}
if(delta > 0) {
gainFame(delta);
}
}
@@ -8503,8 +8545,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
MapleQuest mquest = quest.getQuest();
short questid = mquest.getId();
if(!mquest.isSameDayRepeatable() && !MapleQuest.isExploitableQuest(questid)) {
if(ServerConstants.FAME_GAIN_BY_QUEST > 0)
fameGainByQuest();
awardQuestPoint(ServerConstants.QUEST_POINT_PER_QUEST_COMPLETE);
}
announce(MaplePacketCreator.completeQuest(questid, quest.getCompletionTime()));
@@ -8572,7 +8613,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private void runQuestExpireTask() {
petLock.lock();
try {
long timeNow = System.currentTimeMillis();
long timeNow = Server.getInstance().getCurrentTime();
List<MapleQuest> expireList = new LinkedList<>();
for(Entry<MapleQuest, Long> qe : questExpirations.entrySet()) {
@@ -8607,7 +8648,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}, 10 * 1000);
}
questExpirations.put(quest, System.currentTimeMillis() + time);
questExpirations.put(quest, Server.getInstance().getCurrentTime() + time);
} finally {
petLock.unlock();
}
@@ -8880,6 +8921,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return false;
}
//EVENTS
private byte team = 0;
private MapleFitness fitness;
@@ -8917,6 +8959,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void setLastSnowballAttack(long time) {
this.snowballattack = time;
}
//Monster Carnival
private int cp = 0;
private int obtainedcp = 0;
@@ -9059,7 +9102,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
continue;
}
if ((nEquip.getItemLevel() < ServerConstants.USE_EQUIPMNT_LVLUP) || (itemName.contains("Reverse") && nEquip.getItemLevel() < 4) || (itemName.contains("Timeless") && nEquip.getItemLevel() < 6)) {
if ((nEquip.getItemLevel() < ServerConstants.USE_EQUIPMNT_LVLUP) || (nEquip.getItemLevel() < ii.getEquipLevel(nEquip.getItemId(), true))) {
nEquip.gainItemExp(client, expGain);
}
}

View File

@@ -85,6 +85,8 @@ public class MapleClient {
public static final int LOGIN_SERVER_TRANSITION = 1;
public static final int LOGIN_LOGGEDIN = 2;
public static final String CLIENT_KEY = "CLIENT";
public static final String CLIENT_HWID = "HWID";
public static final String CLIENT_NIBBLEHWID = "HWID2";
private MapleAESOFB send;
private MapleAESOFB receive;
private final IoSession session;
@@ -507,7 +509,7 @@ public class MapleClient {
return false;
}
public int login(String login, String pwd) {
public int login(String login, String pwd, String nibbleHwid) {
loginattempt++;
if (loginattempt > 4) {
MapleSessionCoordinator.getInstance().closeSession(session, false);
@@ -571,7 +573,7 @@ public class MapleClient {
}
if (loginok == 0 || loginok == 4) {
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptSessionLogin(session, accId, loginok == 4);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptLoginSession(session, nibbleHwid, accId, loginok == 4);
switch (res) {
case SUCCESS:
@@ -887,71 +889,59 @@ public class MapleClient {
final World wserv = getWorldServer(); // obviously wserv is NOT null if this player was online on it
try {
if (channel == -1 || shutdown) {
if(chrg != null) chrg.setCharacter(null);
wserv.removePlayer(player);
removePlayer(wserv);
player.saveCooldowns();
player.cancelAllDebuffs();
player.saveCharToDB(true);
clear();
return;
}
removePlayer(wserv);
if (!cashshop) {
if (!this.serverTransition) { // meaning not changing channels
if (messengerid > 0) {
wserv.leaveMessenger(messengerid, chrm);
}
/*
if (fid > 0) {
final MapleFamily family = worlda.getFamily(fid);
family.
if (!(channel == -1 || shutdown)) {
if (!cashshop) {
if (!this.serverTransition) { // meaning not changing channels
if (messengerid > 0) {
wserv.leaveMessenger(messengerid, chrm);
}
/*
if (fid > 0) {
final MapleFamily family = worlda.getFamily(fid);
family.
}
*/
for (MapleQuestStatus status : player.getStartedQuests()) { //This is for those quests that you have to stay logged in for a certain amount of time
MapleQuest quest = status.getQuest();
if (quest.getTimeLimit() > 0) {
MapleQuestStatus newStatus = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
newStatus.setForfeited(player.getQuest(quest).getForfeited() + 1);
player.updateQuest(newStatus);
}
}
if (guild != null) {
final Server server = Server.getInstance();
server.setGuildMemberOnline(player, false, player.getClient().getChannel());
player.getClient().announce(MaplePacketCreator.showGuildInfo(player));
}
if (bl != null) {
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
}
}
*/
for (MapleQuestStatus status : player.getStartedQuests()) { //This is for those quests that you have to stay logged in for a certain amount of time
MapleQuest quest = status.getQuest();
if (quest.getTimeLimit() > 0) {
MapleQuestStatus newStatus = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
newStatus.setForfeited(player.getQuest(quest).getForfeited() + 1);
player.updateQuest(newStatus);
}
}
if (guild != null) {
final Server server = Server.getInstance();
server.setGuildMemberOnline(player, false, player.getClient().getChannel());
player.getClient().announce(MaplePacketCreator.showGuildInfo(player));
}
if (bl != null) {
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
}
}
} else {
if (!this.serverTransition) { // if dc inside of cash shop.
if (bl != null) {
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
}
}
}
} else {
if (!this.serverTransition) { // if dc inside of cash shop.
if (bl != null) {
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
}
}
}
}
} catch (final Exception e) {
FilePrinter.printError(FilePrinter.ACCOUNT_STUCK, e);
} finally {
if (!this.serverTransition) {
if(chrg != null) chrg.setCharacter(null);
wserv.removePlayer(player);
//getChannelServer().removePlayer(player); already being done
player.saveCooldowns();
player.cancelAllDebuffs();
player.saveCharToDB(true);
if (player != null) {//no idea, occur :(
player.empty(false);
}
player.logOff();
clear();
} else {
getChannelServer().removePlayer(player);

View File

@@ -301,7 +301,7 @@ public class CommandsExecutor {
addCommand("servermessage", 4, ServerMessageCommand.class);
addCommand("proitem", 4, ProItemCommand.class);
addCommand("seteqstat", 4, SetQStatCommand.class);
addCommand("seteqstat", 4, SetEqStatCommand.class);
addCommand("exprate", 4, ExpRateCommand.class);
addCommand("mesorate", 4, MesoRateCommand.class);
addCommand("droprate", 4, DropRateCommand.class);

View File

@@ -26,6 +26,7 @@ package client.command.commands.v1;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import constants.GameConstants;
import server.MaplePortal;
import server.maps.MapleMap;
@@ -38,56 +39,7 @@ public class GotoCommand extends Command {
@Override
public void execute(MapleClient c, String[] params) {
final HashMap<String, Integer> gotomaps = new HashMap<String, Integer>();
gotomaps.put("gmmap", 180000000);
gotomaps.put("southperry", 60000);
gotomaps.put("amherst", 1000000);
gotomaps.put("henesys", 100000000);
gotomaps.put("ellinia", 101000000);
gotomaps.put("perion", 102000000);
gotomaps.put("kerning", 103000000);
gotomaps.put("lith", 104000000);
gotomaps.put("sleepywood", 105040300);
gotomaps.put("florina", 110000000);
gotomaps.put("nautilus", 120000000);
gotomaps.put("ereve", 130000000);
gotomaps.put("rien", 140000000);
gotomaps.put("orbis", 200000000);
gotomaps.put("happy", 209000000);
gotomaps.put("elnath", 211000000);
gotomaps.put("ludi", 220000000);
gotomaps.put("aqua", 230000000);
gotomaps.put("leafre", 240000000);
gotomaps.put("mulung", 250000000);
gotomaps.put("herb", 251000000);
gotomaps.put("omega", 221000000);
gotomaps.put("korean", 222000000);
gotomaps.put("ellin", 300000000);
gotomaps.put("nlc", 600000000);
gotomaps.put("excavation", 990000000);
gotomaps.put("pianus", 230040420);
gotomaps.put("horntail", 240060200);
gotomaps.put("mushmom", 100000005);
gotomaps.put("griffey", 240020101);
gotomaps.put("manon", 240020401);
gotomaps.put("horseman", 682000001);
gotomaps.put("balrog", 105090900);
gotomaps.put("zakum", 211042300);
gotomaps.put("papu", 220080001);
gotomaps.put("showa", 801000000);
gotomaps.put("guild", 200000301);
gotomaps.put("shrine", 800000000);
gotomaps.put("skelegon", 240040511);
gotomaps.put("hpq", 100000200);
gotomaps.put("ht", 240050400);
gotomaps.put("ariant", 260000000);
gotomaps.put("magatia", 261000000);
gotomaps.put("singapore", 540000000);
gotomaps.put("keep", 610020006);
gotomaps.put("amoria", 680000000);
gotomaps.put("temple", 270000100);
gotomaps.put("neo", 240070000);
gotomaps.put("fm", 910000000);
final HashMap<String, Integer> gotomaps = GameConstants.GOTO_MAPS;
MapleCharacter player = c.getPlayer();
if (params.length < 1){

View File

@@ -42,11 +42,12 @@ public class ProItemCommand extends Command {
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 2) {
player.yellowMessage("Syntax: !proitem <itemid> <statvalue>");
player.yellowMessage("Syntax: !proitem <itemid> <stat value> [<spdjmp value>]");
return;
}
int itemid = Integer.parseInt(params[0]);
short multiply = Short.parseShort(params[1]);
short stat = (short) Math.max(0, Short.parseShort(params[1]));
short spdjmp = params.length >= 3 ? (short) Math.max(0, Short.parseShort(params[2])) : 0;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemid);
@@ -54,13 +55,13 @@ public class ProItemCommand extends Command {
Item it = ii.getEquipById(itemid);
it.setOwner(player.getName());
hardsetItemStats((Equip) it, multiply);
hardsetItemStats((Equip) it, stat, spdjmp);
MapleInventoryManipulator.addFromDrop(c, it);
} else {
player.dropMessage(6, "Make sure it's an equippable item.");
}
}
private static void hardsetItemStats(Equip equip, short stat) {
private static void hardsetItemStats(Equip equip, short stat, short spdjmp) {
equip.setStr(stat);
equip.setDex(stat);
equip.setInt(stat);
@@ -69,8 +70,8 @@ public class ProItemCommand extends Command {
equip.setWatk(stat);
equip.setAcc(stat);
equip.setAvoid(stat);
equip.setJump(stat);
equip.setSpeed(stat);
equip.setJump(spdjmp);
equip.setSpeed(spdjmp);
equip.setWdef(stat);
equip.setMdef(stat);
equip.setHp(stat);

View File

@@ -31,7 +31,7 @@ import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import constants.ItemConstants;
public class SetQStatCommand extends Command {
public class SetEqStatCommand extends Command {
{
setDescription("");
}
@@ -40,33 +40,33 @@ public class SetQStatCommand extends Command {
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !seteqstat <statvalue>");
player.yellowMessage("Syntax: !seteqstat <stat value> [<spdjmp value>]");
return;
}
int newStat = Integer.parseInt(params[0]);
short newStat = (short) Math.max(0, Integer.parseInt(params[0]));
short newSpdJmp = params.length >= 2 ? (short) Integer.parseInt(params[1]) : 0;
MapleInventory equip = player.getInventory(MapleInventoryType.EQUIP);
for (byte i = 1; i <= equip.getSlotLimit(); i++) {
try {
Equip eu = (Equip) equip.getItem(i);
if (eu == null) continue;
short incval = (short) newStat;
eu.setWdef(incval);
eu.setAcc(incval);
eu.setAvoid(incval);
eu.setJump(incval);
eu.setMatk(incval);
eu.setMdef(incval);
eu.setHp(incval);
eu.setMp(incval);
eu.setSpeed(incval);
eu.setWatk(incval);
eu.setDex(incval);
eu.setInt(incval);
eu.setStr(incval);
eu.setLuk(incval);
eu.setWdef(newStat);
eu.setAcc(newStat);
eu.setAvoid(newStat);
eu.setJump(newSpdJmp);
eu.setMatk(newStat);
eu.setMdef(newStat);
eu.setHp(newStat);
eu.setMp(newStat);
eu.setSpeed(newSpdJmp);
eu.setWatk(newStat);
eu.setDex(newStat);
eu.setInt(newStat);
eu.setStr(newStat);
eu.setLuk(newStat);
byte flag = eu.getFlag();
flag |= ItemConstants.UNTRADEABLE;

View File

@@ -66,7 +66,7 @@ public class Equip extends Item {
private float itemExp;
private int ringid = -1;
private boolean wear = false;
private boolean isUpgradeable, isElemental = false; // timeless or reverse
private boolean isUpgradeable, isElemental = false; // timeless or reverse, or any equip that could levelup on GMS for all effects
public Equip(int id, short position) {
this(id, position, 0);
@@ -78,8 +78,7 @@ public class Equip extends Item {
this.itemExp = 0;
this.itemLevel = 1;
String itemName = MapleItemInformationProvider.getInstance().getName(id);
if(itemName != null) this.isElemental = (itemName.contains("Timeless") || itemName.contains("Reverse"));
this.isElemental = (MapleItemInformationProvider.getInstance().getEquipLevel(id, false) > 1);
}
@Override
@@ -533,17 +532,14 @@ public class Equip extends Item {
}
}
private boolean reachedMaxLevel(String eqpName) {
if(isElemental) {
if(eqpName.contains("Timeless")) {
if(itemLevel < 6) return false;
} else {
if(itemLevel < 4) return false;
private boolean reachedMaxLevel() {
if (isElemental) {
if (itemLevel < MapleItemInformationProvider.getInstance().getEquipLevel(getItemId(), true)) {
return false;
}
}
if(itemLevel < ServerConstants.USE_EQUIPMNT_LVLUP) return false;
return true;
return itemLevel >= ServerConstants.USE_EQUIPMNT_LVLUP;
}
public String showEquipFeatures(MapleClient c) {
@@ -551,7 +547,7 @@ public class Equip extends Item {
if(!ii.isUpgradeable(this.getItemId())) return "";
String eqpName = ii.getName(getItemId());
String eqpInfo = reachedMaxLevel(eqpName) ? " #e#rMAX LEVEL#k#n" : (" EXP: #e#b" + (int)itemExp + "#k#n / " + ExpTable.getEquipExpNeededForLevel(itemLevel));
String eqpInfo = reachedMaxLevel() ? " #e#rMAX LEVEL#k#n" : (" EXP: #e#b" + (int)itemExp + "#k#n / " + ExpTable.getEquipExpNeededForLevel(itemLevel));
return "'" + eqpName + "' -> LV: #e#b" + itemLevel + "#k#n " + eqpInfo + "\r\n";
}

View File

@@ -25,10 +25,12 @@ import constants.ItemConstants;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
public class Item implements Comparable<Item> {
private static AtomicInteger runningCashId = new AtomicInteger(0);
private int id, cashId, sn;
private short position;
private short quantity;
@@ -81,7 +83,7 @@ public class Item implements Comparable<Item> {
public int getCashId() {
if (cashId == 0) {
cashId = new Random().nextInt(Integer.MAX_VALUE) + 1;
cashId = runningCashId.incrementAndGet();
}
return cashId;
}