Implemented Kites, PlayerNPCs and C. Shop Surprise & Tweaked login
Added code support for Kites. Reviewed concurrent access issues with pet autopot. Addressed PlayerStorage issue where characters would not be properly deregistered from channel PlayerStorage in certain situations. Implemented harp quest (questid 3314) because of reasons. Added SFX to signalize KC/NLC subway departing/approaching. Changed traveling time values to work similarly to GMS. Properly developed the PlayerNPC feature in the source. Added autodeployable PlayerNPC system and Hall of Fame. Solved a glitch with NLC mayor's quiz questline that would allow a player to restart the quiz as many times one would see fit. Added a custom server flag that allows overwriting the ToT 999 mobs to a new value (technically it doesn't overwrite, rather sets the player at quest start with 999 - n credited mobs). Fixed permanent pets expiring after a while. Added code support for Cash Shop Surprise item. Reviewed login handler system as a whole, protecting many exposed flaws. Solved a bug with ULTRA_THREE_SNAILS sometimes taking wrong etc shell from inventory.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import client.MapleJob;
|
||||
import constants.skills.Aran;
|
||||
import server.maps.MapleMap;
|
||||
@@ -11,6 +13,9 @@ import server.quest.MapleQuest;
|
||||
* @author Ronan
|
||||
*/
|
||||
public class GameConstants {
|
||||
public static String[] WORLD_NAMES = {"Scania", "Bera", "Broa", "Windia", "Khaini", "Bellocan", "Mardia", "Kradia", "Yellonde", "Demethos", "Galicia", "El Nido", "Zenith", "Arcenia", "Kastia", "Judis", "Plana", "Kalluna", "Stius", "Croa", "Medere"};
|
||||
|
||||
final static Map<Integer, String> jobNames = new HashMap<>();
|
||||
public static final int[] OWL_DATA = new int[]{1082002, 2070005, 2070006, 1022047, 1102041, 2044705, 2340000, 2040017, 1092030, 2040804};
|
||||
|
||||
// Ronan's rates upgrade system
|
||||
@@ -18,6 +23,16 @@ public class GameConstants {
|
||||
private static final int[] MESO_RATE_GAIN = {1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105};
|
||||
private static final int[] EXP_RATE_GAIN = {1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610}; //fibonacci :3
|
||||
|
||||
public static boolean availableDeveloperRoom = false;
|
||||
|
||||
public static void setAvailableDeveloperRoom() {
|
||||
availableDeveloperRoom = true;
|
||||
}
|
||||
|
||||
public static boolean canEnterDeveloperRoom() {
|
||||
return availableDeveloperRoom;
|
||||
}
|
||||
|
||||
public static int getPlayerBonusDropRate(int slot) {
|
||||
return(DROP_RATE_GAIN[slot]);
|
||||
}
|
||||
@@ -63,6 +78,130 @@ 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 String getJobName(int jobid) {
|
||||
String name = jobNames.get(jobid);
|
||||
|
||||
if(name == null) {
|
||||
MapleJob job = MapleJob.getById(jobid);
|
||||
|
||||
if(job != null) {
|
||||
name = job.name().toLowerCase();
|
||||
name = name.replaceAll("[*0-9]", "");
|
||||
name = name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
} else {
|
||||
name = "";
|
||||
}
|
||||
|
||||
jobNames.put(jobid, name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static boolean isHallOfFameMap(int mapid) {
|
||||
switch(mapid) {
|
||||
case 102000004: // warrior
|
||||
case 101000004: // magician
|
||||
case 100000204: // bowman
|
||||
case 103000008: // thief
|
||||
case 120000105: // pirate
|
||||
case 130000100: // cygnus
|
||||
case 130000101: // other cygnus
|
||||
case 130000110: // cygnus 2nd floor
|
||||
case 130000120: // cygnus 3rd floor (beginners)
|
||||
case 140010110: // aran
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte getHallOfFameBranch(MapleJob job, int mapid) {
|
||||
if(!isHallOfFameMap(mapid)) {
|
||||
return (byte) (26 + 4 * (mapid / 100000000)); // custom, 400 pnpcs available per continent
|
||||
}
|
||||
|
||||
if(job.isA(MapleJob.WARRIOR)) {
|
||||
return 10;
|
||||
} else if(job.isA(MapleJob.MAGICIAN)) {
|
||||
return 11;
|
||||
} else if(job.isA(MapleJob.BOWMAN)) {
|
||||
return 12;
|
||||
} else if(job.isA(MapleJob.THIEF)) {
|
||||
return 13;
|
||||
} else if(job.isA(MapleJob.PIRATE)) {
|
||||
return 14;
|
||||
} else if(job.isA(MapleJob.DAWNWARRIOR1)) {
|
||||
return 15;
|
||||
} else if(job.isA(MapleJob.BLAZEWIZARD1)) {
|
||||
return 16;
|
||||
} else if(job.isA(MapleJob.WINDARCHER1)) {
|
||||
return 17;
|
||||
} else if(job.isA(MapleJob.NIGHTWALKER1)) {
|
||||
return 18;
|
||||
} else if(job.isA(MapleJob.THUNDERBREAKER1)) {
|
||||
return 19;
|
||||
} else if(job.isA(MapleJob.ARAN1)) {
|
||||
return 20;
|
||||
} else if(job.isA(MapleJob.EVAN1)) {
|
||||
return 21;
|
||||
} else if(job.isA(MapleJob.BEGINNER)) {
|
||||
return 22;
|
||||
} else if(job.isA(MapleJob.NOBLESSE)) {
|
||||
return 23;
|
||||
} else if(job.isA(MapleJob.LEGEND)) {
|
||||
return 24;
|
||||
} else {
|
||||
return 25;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getOverallJobRankByScriptId(int scriptId) {
|
||||
int branch = (scriptId / 100) % 100;
|
||||
|
||||
if(branch < 26) {
|
||||
return (scriptId % 100) + 1;
|
||||
} else {
|
||||
return ((scriptId - 2600) % 400) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canPnpcBranchUseScriptId(byte branch, int scriptId) {
|
||||
scriptId /= 100;
|
||||
scriptId %= 100;
|
||||
|
||||
if(branch < 26) {
|
||||
return branch == scriptId;
|
||||
} else {
|
||||
return scriptId >= branch && scriptId < branch + 4;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getHallOfFameMapid(MapleJob job) {
|
||||
int jobid = job.getId();
|
||||
|
||||
if(isCygnus(jobid)) {
|
||||
return 130000100;
|
||||
} else if(isAran(jobid)) {
|
||||
return 140010110;
|
||||
} else {
|
||||
if(job.isA(MapleJob.WARRIOR)) {
|
||||
return 102000004;
|
||||
} else if(job.isA(MapleJob.MAGICIAN)) {
|
||||
return 101000004;
|
||||
} else if(job.isA(MapleJob.BOWMAN)) {
|
||||
return 100000204;
|
||||
} else if(job.isA(MapleJob.THIEF)) {
|
||||
return 103000008;
|
||||
} else if(job.isA(MapleJob.PIRATE)) {
|
||||
return 120000105;
|
||||
} else {
|
||||
return 130000110; // beginner explorers are allotted with the Cygnus, available map lul
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getJobBranch(MapleJob job) {
|
||||
int jobid = job.getId();
|
||||
|
||||
@@ -125,6 +264,10 @@ public class GameConstants {
|
||||
return Aran.HIDDEN_FULL_DOUBLE == skill || Aran.HIDDEN_FULL_TRIPLE == skill || Aran.HIDDEN_OVER_DOUBLE == skill || Aran.HIDDEN_OVER_TRIPLE == skill;
|
||||
}
|
||||
|
||||
public static boolean isCygnus(final int job) {
|
||||
return job / 1000 == 1;
|
||||
}
|
||||
|
||||
public static boolean isAran(final int job) {
|
||||
return job == 2000 || (job >= 2100 && job <= 2112);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
package constants;
|
||||
|
||||
import client.inventory.MapleInventoryType;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -42,7 +44,15 @@ public final class ItemConstants {
|
||||
public final static int ACCOUNT_SHARING = 0x100;
|
||||
|
||||
public final static boolean EXPIRING_ITEMS = true;
|
||||
public final static Set<Integer> permanentItemids = new HashSet<>();
|
||||
|
||||
static {
|
||||
int[] pi = {5000060, 5000100, 5000101, 5000102}; // i ain't going to open one gigantic itemid cache just for 4 perma itemids, no way!
|
||||
for(int i : pi) {
|
||||
permanentItemids.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getFlagByInt(int type) {
|
||||
if (type == 128) {
|
||||
return PET_COME;
|
||||
@@ -97,6 +107,10 @@ public final class ItemConstants {
|
||||
return ServerConstants.USE_ERASE_PET_ON_EXPIRATION || itemId == 5000054;
|
||||
}
|
||||
|
||||
public static boolean isPermanentItem(int itemId) {
|
||||
return permanentItemids.contains(itemId);
|
||||
}
|
||||
|
||||
public static boolean isNewYearCardEtc(int itemId) {
|
||||
return itemId / 10000 == 430;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,8 @@ public class ServerConstants {
|
||||
public static String DB_PASS = "";
|
||||
public static final boolean DB_CONNECTION_POOL = true; //Installs a connection pool to hub DB connections. Set false to default.
|
||||
|
||||
//World And Version
|
||||
//Server Version
|
||||
public static short VERSION = 83;
|
||||
public static String[] WORLD_NAMES = {"Scania", "Bera", "Broa", "Windia", "Khaini", "Bellocan", "Mardia", "Kradia", "Yellonde", "Demethos", "Galicia", "El Nido", "Zenith", "Arcenia", "Kastia", "Judis", "Plana", "Kalluna", "Stius", "Croa", "Medere"};
|
||||
|
||||
//Login Configuration
|
||||
public static final int CHANNEL_LOAD = 100; //Max players per channel (limit actually used to calculate the World server capacity).
|
||||
@@ -93,17 +92,19 @@ public class ServerConstants {
|
||||
public static final boolean BLOCK_GENERATE_CASH_ITEM = false; //Prevents creation of cash items with the item/drop command.
|
||||
|
||||
//Miscellaneous Configuration
|
||||
public static final byte MIN_UNDERLEVEL_TO_EXP_GAIN = 5; //Characters are unable to get EXP from a mob if their level are under this threshold, only if "USE_ENFORCE_MOB_LEVEL_RANGE" is enabled. For bosses, this attribute is doubled.
|
||||
public static final byte MAX_MONITORED_BUFFSTATS = 5; //Limits accounting for "dormant" buff effects, that should take place when stronger stat buffs expires.
|
||||
public static String TIMEZONE = "-GMT3";
|
||||
public static boolean USE_UNITPRICE_WITH_COMMA = true; //Set this accordingly with the layout of the unitPrices on Item.wz XML's, whether it's using commas or dots to represent fractions.
|
||||
public static final byte MIN_UNDERLEVEL_TO_EXP_GAIN = 5; //Characters are unable to get EXP from a mob if their level are under this threshold, only if "USE_ENFORCE_MOB_LEVEL_RANGE" is enabled. For bosses, this attribute is doubled.
|
||||
public static final byte MAX_MONITORED_BUFFSTATS = 5; //Limits accounting for "dormant" buff effects, that should take place when stronger stat buffs expires.
|
||||
public static final int MAX_AP = 32767; //Max AP allotted on the auto-assigner.
|
||||
public static final int MAX_EVENT_LEVELS = 8; //Event has different levels of rewarding system.
|
||||
public static final long BLOCK_NPC_RACE_CONDT = (long)(0.5 * 1000); //Time the player client must wait before reopening a conversation with an NPC.
|
||||
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //Time the pet must wait before trying to pick items up.
|
||||
public static boolean USE_UNITPRICE_WITH_COMMA = true; //Set this accordingly with the layout of the unitPrices on Item.wz XML's, whether it's using commas or dots to represent fractions.
|
||||
public static String TIMEZONE = "-GMT3";
|
||||
public static final int TOT_MOB_QUEST_REQUIREMENT = 0; //Overwrites old 999-mobs requirement for the ToT questline with new requirement value, set 0 for default.
|
||||
|
||||
//Dangling Items/Locks Configuration
|
||||
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
|
||||
public static final int KITE_EXPIRE_TIME = 60 * 60 * 1000; //Time before new year (cash item) kite disappears.
|
||||
public static final int ITEM_MONITOR_TIME = 5 * 60 * 1000; //Interval between item monitoring tasks on maps, which checks for dangling (null) item objects on the map item history.
|
||||
public static final int LOCK_MONITOR_TIME = 30 * 1000; //Waiting time for a lock to be released. If it reach timed out, a critical server deadlock has made present.
|
||||
public static final int ITEM_EXPIRE_CHECK = 10 * 1000; //Interval between item expiring tasks on maps, which checks and makes disappear expired items.
|
||||
@@ -145,6 +146,15 @@ public class ServerConstants {
|
||||
public static final byte CHAIR_EXTRA_HEAL_HP = 70; //Each chair extra heal proc increasing HP.
|
||||
public static final byte CHAIR_EXTRA_HEAL_MP = 42; //Each chair extra heal proc increasing MP.
|
||||
|
||||
//Player NPC Configuration
|
||||
public static final int PLAYERNPC_INITIAL_X = 262; //Map frame width for putting PlayerNPCs.
|
||||
public static final int PLAYERNPC_INITIAL_Y = 262; //Map frame height for putting PlayerNPCs.
|
||||
public static final int PLAYERNPC_AREA_X = 320; //Initial width gap between PlayerNPCs.
|
||||
public static final int PLAYERNPC_AREA_Y = 160; //Initial height gap between PlayerNPCs.
|
||||
public static final int PLAYERNPC_AREA_STEPS = 4; //Max number of times gap is shortened to comport PlayerNPCs
|
||||
public static final boolean PLAYERNPC_ORGANIZE_AREA = true; //Automatically rearranges PlayerNPCs on the map if there is no space set the new NPC. Current distance gap between NPCs is decreased to solve this issue.
|
||||
public static final boolean PLAYERNPC_AUTODEPLOY = true; //Makes PlayerNPC automatically deployed on the Hall of Fame at the instant one reaches max level. If false, eligible players must talk to 1st job instructor to deploy a NPC.
|
||||
|
||||
//Pet Auto-Pot Configuration
|
||||
public static final boolean USE_EQUIPS_ON_AUTOPOT = true; //Player MaxHP and MaxMP check values on autopot handler will be updated by the HP/MP bonuses on equipped items.
|
||||
public static final double PET_AUTOHP_RATIO = 0.99; //Will automatically consume potions until given ratio of the MaxHP/MaxMP is reached.
|
||||
|
||||
Reference in New Issue
Block a user