Quest & Command tweak + MapleCashDropFetcher + Cash drop tidyup
Solved a possible exploit on starting/completing non-scripted quests. Added missing drop data for Aran's puppeteer questline. Moved GM tier level of some commands. Applied proper synchronization for BuddyList modules. Issued commands now requires "@" heading for normal players and donators (GM level < 2) and "!" for Jr. GM and above (GM level >= 2). Added custom feature: a message will be sent to acquaintances of a player (friends, family, guild, spouse) when they change/upgrade jobs. Removed cash drop entries from the DB. New tool: MapleCashDropFetcher. Reports on a text file all cash-type drop data on DB.
This commit is contained in:
@@ -26,10 +26,12 @@ import java.sql.ResultSet;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import net.server.PlayerStorage;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -50,15 +52,22 @@ public class BuddyList {
|
||||
}
|
||||
|
||||
public boolean contains(int characterId) {
|
||||
return buddies.containsKey(Integer.valueOf(characterId));
|
||||
synchronized(buddies) {
|
||||
return buddies.containsKey(Integer.valueOf(characterId));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsVisible(int characterId) {
|
||||
BuddylistEntry ble = buddies.get(characterId);
|
||||
BuddylistEntry ble;
|
||||
synchronized(buddies) {
|
||||
ble = buddies.get(characterId);
|
||||
}
|
||||
|
||||
if (ble == null) {
|
||||
return false;
|
||||
}
|
||||
return ble.isVisible();
|
||||
|
||||
}
|
||||
|
||||
public int getCapacity() {
|
||||
@@ -70,42 +79,65 @@ public class BuddyList {
|
||||
}
|
||||
|
||||
public BuddylistEntry get(int characterId) {
|
||||
return buddies.get(Integer.valueOf(characterId));
|
||||
synchronized(buddies) {
|
||||
return buddies.get(Integer.valueOf(characterId));
|
||||
}
|
||||
}
|
||||
|
||||
public BuddylistEntry get(String characterName) {
|
||||
String lowerCaseName = characterName.toLowerCase();
|
||||
for (BuddylistEntry ble : buddies.values()) {
|
||||
for (BuddylistEntry ble : getBuddies()) {
|
||||
if (ble.getName().toLowerCase().equals(lowerCaseName)) {
|
||||
return ble;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void put(BuddylistEntry entry) {
|
||||
buddies.put(Integer.valueOf(entry.getCharacterId()), entry);
|
||||
synchronized(buddies) {
|
||||
buddies.put(Integer.valueOf(entry.getCharacterId()), entry);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(int characterId) {
|
||||
buddies.remove(Integer.valueOf(characterId));
|
||||
synchronized(buddies) {
|
||||
buddies.remove(Integer.valueOf(characterId));
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<BuddylistEntry> getBuddies() {
|
||||
return buddies.values();
|
||||
synchronized(buddies) {
|
||||
return Collections.unmodifiableCollection(buddies.values());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return buddies.size() >= capacity;
|
||||
synchronized(buddies) {
|
||||
return buddies.size() >= capacity;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getBuddyIds() {
|
||||
int buddyIds[] = new int[buddies.size()];
|
||||
int i = 0;
|
||||
for (BuddylistEntry ble : buddies.values()) {
|
||||
buddyIds[i++] = ble.getCharacterId();
|
||||
synchronized(buddies) {
|
||||
int buddyIds[] = new int[buddies.size()];
|
||||
int i = 0;
|
||||
for (BuddylistEntry ble : buddies.values()) {
|
||||
buddyIds[i++] = ble.getCharacterId();
|
||||
}
|
||||
return buddyIds;
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcast(byte[] packet, PlayerStorage pstorage) {
|
||||
for(int bid : getBuddyIds()) {
|
||||
MapleCharacter chr = pstorage.getCharacterById(bid);
|
||||
|
||||
if(chr != null && chr.isLoggedin() && !chr.isAwayFromWorld()) {
|
||||
chr.announce(packet);
|
||||
}
|
||||
}
|
||||
return buddyIds;
|
||||
}
|
||||
|
||||
public void loadFromDb(int characterId) {
|
||||
|
||||
@@ -199,7 +199,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private int expRate = 1, mesoRate = 1, dropRate = 1, expCoupon = 1, mesoCoupon = 1, dropCoupon = 1;
|
||||
private int omokwins, omokties, omoklosses, matchcardwins, matchcardties, matchcardlosses;
|
||||
private int owlSearch;
|
||||
private int married;
|
||||
private long lastfametime, lastUsedCashItem, lastHealed, lastMesoDrop = -1, jailExpiration = -1;
|
||||
private transient int localmaxhp, localmaxmp, localstr, localdex, localluk, localint_, magic, watk;
|
||||
private boolean hidden, canDoor = true, berserk, hasMerchant, whiteChat = false;
|
||||
@@ -1093,6 +1092,36 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
createDragon();
|
||||
}
|
||||
|
||||
if(ServerConstants.USE_ANNOUNCE_CHANGEJOB) {
|
||||
if(gmLevel > 1) {
|
||||
broadcastAcquaintances(6, "[" + GameConstants.ordinal(GameConstants.getJobBranch(newJob)) + " Job] " + name + " has just become a " + newJob.name() + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastAcquaintances(int type, String message) {
|
||||
broadcastAcquaintances(MaplePacketCreator.serverNotice(type, message));
|
||||
}
|
||||
|
||||
public void broadcastAcquaintances(byte[] packet) {
|
||||
buddylist.broadcast(packet, client.getWorldServer().getPlayerStorage());
|
||||
|
||||
if(family != null) {
|
||||
//family.broadcast(packet, id); not yet implemented
|
||||
}
|
||||
|
||||
MapleGuild guild = getGuild();
|
||||
if(guild != null) {
|
||||
guild.broadcast(packet, id);
|
||||
}
|
||||
|
||||
/*
|
||||
if(partnerid > 0) {
|
||||
partner.announce(packet); not yet implemented
|
||||
}
|
||||
*/
|
||||
announce(packet);
|
||||
}
|
||||
|
||||
public void changeKeybinding(int key, MapleKeyBinding keybinding) {
|
||||
@@ -3955,10 +3984,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
return marriageRing;
|
||||
}
|
||||
|
||||
public int getMarried() {
|
||||
return married;
|
||||
}
|
||||
|
||||
public int getMasterLevel(Skill skill) {
|
||||
if (skills.get(skill) == null) {
|
||||
return 0;
|
||||
|
||||
@@ -351,7 +351,7 @@ public class Commands {
|
||||
case "playercommands":
|
||||
c.getAbstractPlayerInteraction().openNpc(9201143, "commands");
|
||||
break;
|
||||
|
||||
|
||||
case "droplimit":
|
||||
int dropCount = c.getPlayer().getMap().getDroppedItemCount();
|
||||
if(((float) dropCount) / ServerConstants.ITEM_LIMIT_ON_MAP < 0.75f) {
|
||||
@@ -402,90 +402,14 @@ public class Commands {
|
||||
}
|
||||
break;
|
||||
}
|
||||
String output = "The #b" + gachaName + "#k Gachapon contains the following items.\r\n\r\n";
|
||||
String talkStr = "The #b" + gachaName + "#k Gachapon contains the following items.\r\n\r\n";
|
||||
for (int i = 0; i < 2; i++){
|
||||
for (int id : gacha.getItems(i)){
|
||||
output += "-" + MapleItemInformationProvider.getInstance().getName(id) + "\r\n";
|
||||
talkStr += "-" + MapleItemInformationProvider.getInstance().getName(id) + "\r\n";
|
||||
}
|
||||
}
|
||||
output += "\r\nPlease keep in mind that there are items that are in all gachapons and are not listed here.";
|
||||
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
|
||||
break;
|
||||
|
||||
case "whatdropsfrom":
|
||||
if (sub.length < 2) {
|
||||
player.dropMessage(5, "Please do @whatdropsfrom <monster name>");
|
||||
break;
|
||||
}
|
||||
String monsterName = joinStringFrom(sub, 1);
|
||||
output = "";
|
||||
int limit = 3;
|
||||
Iterator<Pair<Integer, String>> listIterator = MapleMonsterInformationProvider.getMobsIDsFromName(monsterName).iterator();
|
||||
for (int i = 0; i < limit; i++) {
|
||||
if(listIterator.hasNext()) {
|
||||
Pair<Integer, String> data = listIterator.next();
|
||||
int mobId = data.getLeft();
|
||||
String mobName = data.getRight();
|
||||
output += mobName + " drops the following items:\r\n\r\n";
|
||||
for (MonsterDropEntry drop : MapleMonsterInformationProvider.getInstance().retrieveDrop(mobId)){
|
||||
try {
|
||||
String name = MapleItemInformationProvider.getInstance().getName(drop.itemId);
|
||||
if (name.equals("null") || drop.chance == 0){
|
||||
continue;
|
||||
}
|
||||
float chance = 1000000 / drop.chance / player.getDropRate();
|
||||
output += "- " + name + " (1/" + (int) chance + ")\r\n";
|
||||
} catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
output += "\r\n";
|
||||
}
|
||||
}
|
||||
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
|
||||
break;
|
||||
|
||||
case "whodrops":
|
||||
if (sub.length < 2) {
|
||||
player.dropMessage(5, "Please do @whodrops <item name>");
|
||||
break;
|
||||
}
|
||||
String searchString = joinStringFrom(sub, 1);
|
||||
output = "";
|
||||
listIterator = MapleItemInformationProvider.getInstance().getItemDataByName(searchString).iterator();
|
||||
if(listIterator.hasNext()) {
|
||||
int count = 1;
|
||||
while(listIterator.hasNext() && count <= 3) {
|
||||
Pair<Integer, String> data = listIterator.next();
|
||||
output += "#b" + data.getRight() + "#k is dropped by:\r\n";
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE itemid = ? LIMIT 50");
|
||||
ps.setInt(1, data.getLeft());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
String resultName = MapleMonsterInformationProvider.getMobNameFromID(rs.getInt("dropperid"));
|
||||
if (resultName != null) {
|
||||
output += resultName + ", ";
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch (Exception e) {
|
||||
player.dropMessage(6, "There was a problem retrieving the required data. Please try again.");
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
output += "\r\n\r\n";
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
player.dropMessage(5, "The item you searched for doesn't exist.");
|
||||
break;
|
||||
}
|
||||
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
|
||||
talkStr += "\r\nPlease keep in mind that there are items that are in all gachapons and are not listed here.";
|
||||
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, talkStr, "00 00", (byte) 0));
|
||||
break;
|
||||
|
||||
case "dispose":
|
||||
@@ -560,7 +484,7 @@ public class Commands {
|
||||
player.dropMessage(5, tips[Randomizer.nextInt(tips.length)]);
|
||||
break;
|
||||
|
||||
case "bug":
|
||||
case "reportbug":
|
||||
|
||||
if (sub.length < 2) {
|
||||
player.dropMessage(5, "Message too short and not sent. Please do @bug <bug>");
|
||||
@@ -636,30 +560,6 @@ public class Commands {
|
||||
}
|
||||
break;
|
||||
|
||||
case "bosshp":
|
||||
for(MapleMonster monster : player.getMap().getMonsters()) {
|
||||
if(monster != null && monster.isBoss() && monster.getHp() > 0) {
|
||||
long percent = monster.getHp() * 100L / monster.getMaxHp();
|
||||
String bar = "[";
|
||||
for (int i = 0; i < 100; i++){
|
||||
bar += i < percent ? "|" : ".";
|
||||
}
|
||||
bar += "]";
|
||||
player.yellowMessage(monster.getName() + " (" + monster.getId() + ") has " + percent + "% HP left.");
|
||||
player.yellowMessage("HP: " + bar);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "mobhp":
|
||||
for(MapleMonster monster : player.getMap().getMonsters()) {
|
||||
if(monster != null && monster.getHp() > 0) {
|
||||
player.yellowMessage(monster.getName() + " (" + monster.getId() + ") has " + monster.getHp() + " / " + monster.getMaxHp() + " HP.");
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "ranks":
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -691,6 +591,47 @@ public class Commands {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// stat autoassigning command credited to HeliosMS dev team
|
||||
case "str":
|
||||
case "int":
|
||||
case "luk":
|
||||
case "dex":
|
||||
int amount = (sub.length > 1) ? Integer.parseInt(sub[1]) : player.getRemainingAp();
|
||||
boolean str = sub[0].equalsIgnoreCase("str");
|
||||
boolean Int = sub[0].equalsIgnoreCase("int");
|
||||
boolean luk = sub[0].equalsIgnoreCase("luk");
|
||||
boolean dex = sub[0].equalsIgnoreCase("dex");
|
||||
|
||||
if (amount > 0 && amount <= player.getRemainingAp() && amount <= 32763 || amount < 0 && amount >= -32763 && Math.abs(amount) + player.getRemainingAp() <= 32767) {
|
||||
if (str && amount + player.getStr() <= 32767 && amount + player.getStr() >= 4) {
|
||||
player.setStr(player.getStr() + amount);
|
||||
player.updateSingleStat(MapleStat.STR, player.getStr());
|
||||
player.setRemainingAp(player.getRemainingAp() - amount);
|
||||
player.updateSingleStat(MapleStat.AVAILABLEAP, player.getRemainingAp());
|
||||
} else if (Int && amount + player.getInt() <= 32767 && amount + player.getInt() >= 4) {
|
||||
player.setInt(player.getInt() + amount);
|
||||
player.updateSingleStat(MapleStat.INT, player.getInt());
|
||||
player.setRemainingAp(player.getRemainingAp() - amount);
|
||||
player.updateSingleStat(MapleStat.AVAILABLEAP, player.getRemainingAp());
|
||||
} else if (luk && amount + player.getLuk() <= 32767 && amount + player.getLuk() >= 4) {
|
||||
player.setLuk(player.getLuk() + amount);
|
||||
player.updateSingleStat(MapleStat.LUK, player.getLuk());
|
||||
player.setRemainingAp(player.getRemainingAp() - amount);
|
||||
player.updateSingleStat(MapleStat.AVAILABLEAP, player.getRemainingAp());
|
||||
} else if (dex && amount + player.getDex() <= 32767 && amount + player.getDex() >= 4) {
|
||||
player.setDex(player.getDex() + amount);
|
||||
player.updateSingleStat(MapleStat.DEX, player.getDex());
|
||||
player.setRemainingAp(player.getRemainingAp() - amount);
|
||||
player.updateSingleStat(MapleStat.AVAILABLEAP, player.getRemainingAp());
|
||||
} else {
|
||||
player.dropMessage("Please make sure the stat you are trying to raise is not over 32,767 or under 4.");
|
||||
}
|
||||
} else {
|
||||
player.dropMessage("Please make sure your AP is not over 32,767 and you have enough to distribute.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
@@ -702,8 +643,113 @@ public class Commands {
|
||||
public static boolean executeHeavenMsCommandLv1(Channel cserv, Server srv, MapleClient c, String[] sub) { //Donator
|
||||
MapleCharacter player = c.getPlayer();
|
||||
|
||||
switch(sub[0]) {
|
||||
switch(sub[0]) {
|
||||
case "bosshp":
|
||||
for(MapleMonster monster : player.getMap().getMonsters()) {
|
||||
if(monster != null && monster.isBoss() && monster.getHp() > 0) {
|
||||
long percent = monster.getHp() * 100L / monster.getMaxHp();
|
||||
String bar = "[";
|
||||
for (int i = 0; i < 100; i++){
|
||||
bar += i < percent ? "|" : ".";
|
||||
}
|
||||
bar += "]";
|
||||
player.yellowMessage(monster.getName() + " (" + monster.getId() + ") has " + percent + "% HP left.");
|
||||
player.yellowMessage("HP: " + bar);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "mobhp":
|
||||
for(MapleMonster monster : player.getMap().getMonsters()) {
|
||||
if(monster != null && monster.getHp() > 0) {
|
||||
player.yellowMessage(monster.getName() + " (" + monster.getId() + ") has " + monster.getHp() + " / " + monster.getMaxHp() + " HP.");
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "whatdropsfrom":
|
||||
if (sub.length < 2) {
|
||||
player.dropMessage(5, "Please do @whatdropsfrom <monster name>");
|
||||
break;
|
||||
}
|
||||
String monsterName = joinStringFrom(sub, 1);
|
||||
String output = "";
|
||||
int limit = 3;
|
||||
Iterator<Pair<Integer, String>> listIterator = MapleMonsterInformationProvider.getMobsIDsFromName(monsterName).iterator();
|
||||
for (int i = 0; i < limit; i++) {
|
||||
if(listIterator.hasNext()) {
|
||||
Pair<Integer, String> data = listIterator.next();
|
||||
int mobId = data.getLeft();
|
||||
String mobName = data.getRight();
|
||||
output += mobName + " drops the following items:\r\n\r\n";
|
||||
for (MonsterDropEntry drop : MapleMonsterInformationProvider.getInstance().retrieveDrop(mobId)){
|
||||
try {
|
||||
String name = MapleItemInformationProvider.getInstance().getName(drop.itemId);
|
||||
if (name.equals("null") || drop.chance == 0){
|
||||
continue;
|
||||
}
|
||||
float chance = 1000000 / drop.chance / player.getDropRate();
|
||||
output += "- " + name + " (1/" + (int) chance + ")\r\n";
|
||||
} catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
output += "\r\n";
|
||||
}
|
||||
}
|
||||
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
|
||||
break;
|
||||
|
||||
case "whodrops":
|
||||
if (sub.length < 2) {
|
||||
player.dropMessage(5, "Please do @whodrops <item name>");
|
||||
break;
|
||||
}
|
||||
String searchString = joinStringFrom(sub, 1);
|
||||
output = "";
|
||||
listIterator = MapleItemInformationProvider.getInstance().getItemDataByName(searchString).iterator();
|
||||
if(listIterator.hasNext()) {
|
||||
int count = 1;
|
||||
while(listIterator.hasNext() && count <= 3) {
|
||||
Pair<Integer, String> data = listIterator.next();
|
||||
output += "#b" + data.getRight() + "#k is dropped by:\r\n";
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE itemid = ? LIMIT 50");
|
||||
ps.setInt(1, data.getLeft());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
String resultName = MapleMonsterInformationProvider.getMobNameFromID(rs.getInt("dropperid"));
|
||||
if (resultName != null) {
|
||||
output += resultName + ", ";
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch (Exception e) {
|
||||
player.dropMessage(6, "There was a problem retrieving the required data. Please try again.");
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
output += "\r\n\r\n";
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
player.dropMessage(5, "The item you searched for doesn't exist.");
|
||||
break;
|
||||
}
|
||||
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
|
||||
break;
|
||||
|
||||
case "buffme":
|
||||
if(!player.isGM()) {
|
||||
player.dropMessage(5, "You are already dead.");
|
||||
break;
|
||||
}
|
||||
|
||||
//GM Skills : Haste(Super) - Holy Symbol - Bless - Hyper Body - Echo of Hero
|
||||
SkillFactory.getSkill(4101004).getEffect(SkillFactory.getSkill(4101004).getMaxLevel()).applyTo(player);
|
||||
SkillFactory.getSkill(2311003).getEffect(SkillFactory.getSkill(2311003).getMaxLevel()).applyTo(player);
|
||||
@@ -753,7 +799,20 @@ public class Commands {
|
||||
}
|
||||
player.dropMessage(5, "USE Recharged.");
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean executeHeavenMsCommandLv2(Channel cserv, Server srv, MapleClient c, String[] sub) { //JrGM
|
||||
MapleCharacter player = c.getPlayer();
|
||||
MapleCharacter victim;
|
||||
Skill skill;
|
||||
|
||||
switch(sub[0]) {
|
||||
case "whereami":
|
||||
player.yellowMessage("Map ID: " + player.getMap().getId());
|
||||
player.yellowMessage("Players on this map:");
|
||||
@@ -777,21 +836,8 @@ public class Commands {
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean executeHeavenMsCommandLv2(Channel cserv, Server srv, MapleClient c, String[] sub) { //JrGM
|
||||
MapleCharacter player = c.getPlayer();
|
||||
MapleCharacter victim;
|
||||
Skill skill;
|
||||
|
||||
switch(sub[0]) {
|
||||
break;
|
||||
|
||||
case "hide":
|
||||
SkillFactory.getSkill(9101004).getEffect(SkillFactory.getSkill(9101004).getMaxLevel()).applyTo(player);
|
||||
break;
|
||||
|
||||
@@ -62,26 +62,36 @@ public class GameConstants {
|
||||
330000, 340000, 350000, 360000, 370000, 380000, 390000, 400000, 410000, 420000, 430000, 440000, 450000, 460000, 470000, 480000, 490000, 500000, 510000, 520000,
|
||||
530000, 550000, 570000, 590000, 610000, 630000, 650000, 670000, 690000, 710000, 730000, 750000, 770000, 790000, 810000, 830000, 850000, 870000, 890000, 910000};
|
||||
|
||||
public static int getJobMaxLevel(MapleJob job) {
|
||||
if(job.getId() % 1000 == 0) { // beginner
|
||||
return 10;
|
||||
|
||||
} else if(job.getId() % 100 == 0) { // 1st job
|
||||
return 30;
|
||||
|
||||
public static int getJobBranch(MapleJob job) {
|
||||
int jobid = job.getId();
|
||||
|
||||
if(jobid % 1000 == 0) {
|
||||
return 0;
|
||||
} else if(jobid % 100 == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
int jobBranch = job.getId() % 10;
|
||||
|
||||
switch(jobBranch) {
|
||||
case 0:
|
||||
return 70; // 2nd job
|
||||
|
||||
case 1:
|
||||
return 120; // 3rd job
|
||||
|
||||
default:
|
||||
return (job.getId() / 1000 == 1) ? 120 : 200; // 4th job: cygnus is 120, rest is 200
|
||||
}
|
||||
return 2 + (jobid % 10);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getJobMaxLevel(MapleJob job) {
|
||||
int jobBranch = getJobBranch(job);
|
||||
|
||||
switch(jobBranch) {
|
||||
case 0:
|
||||
return 10; // beginner
|
||||
|
||||
case 1:
|
||||
return 30; // 1st job
|
||||
|
||||
case 2:
|
||||
return 70; // 2nd job
|
||||
|
||||
case 3:
|
||||
return 120; // 3rd job
|
||||
|
||||
default:
|
||||
return (job.getId() / 1000 == 1) ? 120 : 200; // 4th job: cygnus is 120, rest is 200
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,4 +235,17 @@ public class GameConstants {
|
||||
}
|
||||
return mobHpVal[level];
|
||||
}
|
||||
|
||||
public static String ordinal(int i) {
|
||||
String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
|
||||
switch (i % 100) {
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
return i + "th";
|
||||
|
||||
default:
|
||||
return i + sufixes[i % 10];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ public class ServerConstants {
|
||||
public static final boolean USE_QUEST_RATE = false; //Exp/Meso gained by quests uses fixed server exp/meso rate times quest rate as multiplier, instead of player rates.
|
||||
public static final boolean USE_MULTIPLE_SAME_EQUIP_DROP = true;//Enables multiple drops by mobs of the same equipment, number of possible drops based on the quantities provided at the drop data.
|
||||
|
||||
|
||||
//Announcement Configuration
|
||||
public static final boolean USE_ANNOUNCE_CHANGEJOB = true; //Automatic message sent to acquantainces when changing jobs.
|
||||
|
||||
//Server Rates And Experience
|
||||
public static final int EXP_RATE = 10;
|
||||
public static final int MESO_RATE = 10;
|
||||
@@ -158,7 +162,7 @@ public class ServerConstants {
|
||||
public static final boolean USE_DEADLY_DOJO = false; //Should bosses really use 1HP,1MP attacks in dojo?
|
||||
public static final int DOJO_ENERGY_ATK = 100; //Dojo energy gain when deal attack
|
||||
public static final int DOJO_ENERGY_DMG = 20; //Dojo energy gain when recv attack
|
||||
|
||||
|
||||
//Event End Timestamp
|
||||
public static final long EVENT_END_TIMESTAMP = 1428897600000L;
|
||||
|
||||
|
||||
@@ -32,6 +32,14 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
private static boolean isCommandIssue(char heading, MapleCharacter chr) {
|
||||
if(chr.gmLevel() > 1 && heading == '!') {
|
||||
return true;
|
||||
} else {
|
||||
return heading == '@';
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
String s = slea.readMapleAsciiString();
|
||||
@@ -47,7 +55,7 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
char heading = s.charAt(0);
|
||||
if (heading == '!' || heading == '@') {
|
||||
if (isCommandIssue(heading, chr)) {
|
||||
String[] sp = s.split(" ");
|
||||
sp[0] = sp[0].toLowerCase().substring(1);
|
||||
|
||||
|
||||
@@ -44,15 +44,21 @@ public final class QuestActionHandler extends AbstractMaplePacketHandler {
|
||||
if (slea.available() >= 4) {
|
||||
slea.readInt();
|
||||
}
|
||||
quest.start(player, npc);
|
||||
|
||||
if(quest.canStart(player, npc)) {
|
||||
quest.start(player, npc);
|
||||
}
|
||||
} else if (action == 2) { // Complete Quest
|
||||
int npc = slea.readInt();
|
||||
slea.readInt();
|
||||
if (slea.available() >= 2) {
|
||||
int selection = slea.readShort();
|
||||
quest.complete(player, npc, selection);
|
||||
} else {
|
||||
quest.complete(player, npc);
|
||||
|
||||
if(quest.canComplete(player, npc)) {
|
||||
if (slea.available() >= 2) {
|
||||
int selection = slea.readShort();
|
||||
quest.complete(player, npc, selection);
|
||||
} else {
|
||||
quest.complete(player, npc);
|
||||
}
|
||||
}
|
||||
} else if (action == 3) {// forfeit quest
|
||||
quest.forfeit(player);
|
||||
|
||||
@@ -34,6 +34,7 @@ import javax.script.Invocable;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import constants.ServerConstants;
|
||||
import constants.GameConstants;
|
||||
import client.MapleCharacter;
|
||||
import net.server.Server;
|
||||
import net.server.world.World;
|
||||
@@ -499,19 +500,6 @@ public class EventManager {
|
||||
return(MapleLifeFactory.getMonster(mid));
|
||||
}
|
||||
|
||||
private static String ordinal(int i) {
|
||||
String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
|
||||
switch (i % 100) {
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
return i + "th";
|
||||
|
||||
default:
|
||||
return i + sufixes[i % 10];
|
||||
}
|
||||
}
|
||||
|
||||
private void exportReadyGuild(Integer guildId) {
|
||||
MapleGuild mg = server.getGuild(guildId);
|
||||
String callout = "[Guild Quest] Your guild has been registered to attend to the Sharenian Guild Quest at channel " + this.getChannelServer().getId()
|
||||
@@ -524,7 +512,7 @@ public class EventManager {
|
||||
private void exportMovedQueueToGuild(Integer guildId, int place) {
|
||||
MapleGuild mg = server.getGuild(guildId);
|
||||
String callout = "[Guild Quest] Your guild has been registered to attend to the Sharenian Guild Quest at channel " + this.getChannelServer().getId()
|
||||
+ " and is currently on the " + ordinal(place) + " place on the waiting queue.";
|
||||
+ " and is currently on the " + GameConstants.ordinal(place) + " place on the waiting queue.";
|
||||
|
||||
mg.dropMessage(6, callout);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class QuestScriptManager extends AbstractScriptManager {
|
||||
qms.put(c, qm);
|
||||
Invocable iv = getInvocable("quest/" + questid + ".js", c);
|
||||
if (iv == null) {
|
||||
FilePrinter.printError(FilePrinter.QUEST_UNCODED, "Quest " + questid + " is uncoded.\r\n");
|
||||
FilePrinter.printError(FilePrinter.QUEST_UNCODED, "START Quest " + questid + " is uncoded.\r\n");
|
||||
}
|
||||
if (iv == null || QuestScriptManager.getInstance() == null) {
|
||||
qm.dispose();
|
||||
@@ -112,6 +112,7 @@ public class QuestScriptManager extends AbstractScriptManager {
|
||||
qms.put(c, qm);
|
||||
Invocable iv = getInvocable("quest/" + questid + ".js", c);
|
||||
if (iv == null) {
|
||||
FilePrinter.printError(FilePrinter.QUEST_UNCODED, "END Quest " + questid + " is uncoded.\r\n");
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -535,8 +535,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}, getAnimationTime("die1"));
|
||||
}
|
||||
}
|
||||
else { // is this even necessary?
|
||||
} else { // is this even necessary?
|
||||
System.out.println("[CRITICAL LOSS] toSpawn is null for " + this.getName());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user