KerningPQ + some boosts on PQ/event scripting
Added cleaner mechanics for dealing with PQs and events (bonus Exp when clearing a stage, for instance). Reimplemented KerningPQ.
This commit is contained in:
@@ -151,9 +151,17 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private static final int[] EXP_RATE_GAIN = {1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144}; //fibonacci :3
|
||||
|
||||
private static final String LEVEL_200 = "[Congrats] %s has reached Level 200! Congratulate %s on such an amazing achievement!";
|
||||
|
||||
// MapleStory default keyset
|
||||
private static final int[] DEFAULT_KEY = {18, 65, 2, 23, 3, 4, 5, 6, 16, 17, 19, 25, 26, 27, 31, 34, 35, 37, 38, 40, 43, 44, 45, 46, 50, 56, 59, 60, 61, 62, 63, 64, 57, 48, 29, 7, 24, 33, 41, 39};
|
||||
private static final int[] DEFAULT_TYPE = {4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 5, 6, 6, 6, 6, 6, 6, 5, 4, 5, 4, 4, 4, 4, 4};
|
||||
private static final int[] DEFAULT_ACTION = {0, 106, 10, 1, 12, 13, 18, 24, 8, 5, 4, 19, 14, 15, 2, 17, 11, 3, 20, 16, 9, 50, 51, 6, 7, 53, 100, 101, 102, 103, 104, 105, 54, 22, 52, 21, 25, 26, 23, 27};
|
||||
|
||||
// MapleSolaxiaV2 custom keyset
|
||||
private static final int[] CUSTOM_KEY = {2, 3, 4, 5, 31, 56, 59, 32, 42, 6, 17, 29, 30, 41, 50, 60, 61, 62, 63, 64, 65, 16, 7, 8};
|
||||
private static final int[] CUSTOM_TYPE = {4, 4, 4, 4, 5, 5, 6, 5, 5, 4, 4, 4, 5, 4, 4, 6, 6, 6, 6, 6, 6, 4, 4, 4};
|
||||
private static final int[] CUSTOM_ACTION = {1, 0, 3, 2, 53, 54, 100, 52, 51, 19, 5, 9, 50, 7, 22, 101, 102, 103, 104, 105, 106, 8, 17, 26};
|
||||
|
||||
private static final String[] BLOCKED_NAMES = {"admin", "owner", "moderator", "intern", "donor", "administrator", "help", "helper", "alert", "notice", "maplestory", "Solaxia", "fuck", "wizet", "fucking", "negro", "fuk", "fuc", "penis", "pussy", "asshole", "gay",
|
||||
"nigger", "homo", "suck", "cum", "shit", "shitty", "condom", "security", "official", "rape", "nigga", "sex", "tit", "boner", "orgy", "clit", "asshole", "fatass", "bitch", "support", "gamemaster", "cock", "gaay", "gm",
|
||||
"operate", "master", "sysop", "party", "GameMaster", "community", "message", "event", "test", "meso", "Scania", "renewal", "yata", "AsiaSoft", "henesys"};
|
||||
@@ -354,9 +362,28 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
ret.getInventory(MapleInventoryType.USE).setSlotLimit(24);
|
||||
ret.getInventory(MapleInventoryType.SETUP).setSlotLimit(24);
|
||||
ret.getInventory(MapleInventoryType.ETC).setSlotLimit(24);
|
||||
for (int i = 0; i < DEFAULT_KEY.length; i++) {
|
||||
ret.keymap.put(DEFAULT_KEY[i], new MapleKeyBinding(DEFAULT_TYPE[i], DEFAULT_ACTION[i]));
|
||||
|
||||
// Select a keybinding method
|
||||
int[] selectedKey;
|
||||
int[] selectedType;
|
||||
int[] selectedAction;
|
||||
|
||||
if(ServerConstants.USE_CUSTOM_KEYSET) {
|
||||
selectedKey = CUSTOM_KEY;
|
||||
selectedType = CUSTOM_TYPE;
|
||||
selectedAction = CUSTOM_ACTION;
|
||||
}
|
||||
else {
|
||||
selectedKey = DEFAULT_KEY;
|
||||
selectedType = DEFAULT_TYPE;
|
||||
selectedAction = DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
for (int i = 0; i < selectedKey.length; i++) {
|
||||
ret.keymap.put(selectedKey[i], new MapleKeyBinding(selectedType[i], selectedAction[i]));
|
||||
}
|
||||
|
||||
|
||||
//to fix the map 0 lol
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ret.trockmaps.add(999999999);
|
||||
@@ -1206,6 +1233,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
newWarpMap = -1;
|
||||
changeMap(temp);
|
||||
}
|
||||
|
||||
// if this event map has a gate already opened, render it
|
||||
if(getEventInstance() != null) {
|
||||
getEventInstance().recoverOpenedGate(this, map.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void changePage(int page) {
|
||||
@@ -1714,6 +1746,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
this.addFame(delta);
|
||||
this.updateSingleStat(MapleStat.FAME, this.fame);
|
||||
}
|
||||
|
||||
public void gainMeso(int gain) {
|
||||
gainMeso(gain, true, false, true);
|
||||
}
|
||||
|
||||
public void gainMeso(int gain, boolean show) {
|
||||
gainMeso(gain, show, false, false);
|
||||
@@ -3475,7 +3511,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
int lastQuestProcessed = 0;
|
||||
try {
|
||||
for (MapleQuestStatus q : quests.values()) {
|
||||
lastQuestProcessed = q.getQuest().getId();
|
||||
lastQuestProcessed = q.getQuest().getId();
|
||||
if (q.getStatus() == MapleQuestStatus.Status.COMPLETED || q.getQuest().canComplete(this, null)) {
|
||||
continue;
|
||||
}
|
||||
@@ -4037,12 +4073,28 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select a keybinding method
|
||||
int[] selectedKey;
|
||||
int[] selectedType;
|
||||
int[] selectedAction;
|
||||
|
||||
if(ServerConstants.USE_CUSTOM_KEYSET) {
|
||||
selectedKey = CUSTOM_KEY;
|
||||
selectedType = CUSTOM_TYPE;
|
||||
selectedAction = CUSTOM_ACTION;
|
||||
}
|
||||
else {
|
||||
selectedKey = DEFAULT_KEY;
|
||||
selectedType = DEFAULT_TYPE;
|
||||
selectedAction = DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
ps = con.prepareStatement("INSERT INTO keymap (characterid, `key`, `type`, `action`) VALUES (?, ?, ?, ?)");
|
||||
ps.setInt(1, id);
|
||||
for (int i = 0; i < DEFAULT_KEY.length; i++) {
|
||||
ps.setInt(2, DEFAULT_KEY[i]);
|
||||
ps.setInt(3, DEFAULT_TYPE[i]);
|
||||
ps.setInt(4, DEFAULT_ACTION[i]);
|
||||
for (int i = 0; i < selectedKey.length; i++) {
|
||||
ps.setInt(2, selectedKey[i]);
|
||||
ps.setInt(3, selectedType[i]);
|
||||
ps.setInt(4, selectedAction[i]);
|
||||
ps.execute();
|
||||
}
|
||||
ps.close();
|
||||
@@ -4203,6 +4255,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
ps.addBatch();
|
||||
}
|
||||
ps.executeBatch();
|
||||
|
||||
deleteWhereCharacterId(con, "DELETE FROM skillmacros WHERE characterid = ?");
|
||||
ps = con.prepareStatement("INSERT INTO skillmacros (characterid, skill1, skill2, skill3, name, shout, position) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
ps.setInt(1, getId());
|
||||
|
||||
@@ -24,6 +24,7 @@ public class ServerConstants {
|
||||
public static boolean JAVA_8;
|
||||
public static boolean SHUTDOWNHOOK;
|
||||
//Gameplay Configurations
|
||||
public static final boolean USE_CUSTOM_KEYSET = true;
|
||||
public static final boolean USE_MAXRANGE = true; //will send and receive packets from all events of a map, rather than those of only view range.
|
||||
public static final boolean USE_DEBUG = true; //will enable some text prints and new commands in the client oriented for debugging.
|
||||
public static final boolean USE_MTS = false;
|
||||
|
||||
@@ -35,28 +35,30 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
public final class KeymapChangeHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
if (slea.available() >= 8) {
|
||||
if (slea.available() >= 8) {
|
||||
int mode = slea.readInt();
|
||||
if(mode == 0) {
|
||||
int numChanges = slea.readInt();
|
||||
for (int i = 0; i < numChanges; i++) {
|
||||
int key = slea.readInt();
|
||||
int type = slea.readByte();
|
||||
int action = slea.readInt();
|
||||
int action = slea.readInt();
|
||||
|
||||
Skill skill = SkillFactory.getSkill(action);
|
||||
boolean isBanndedSkill = false;
|
||||
if (skill != null) {
|
||||
isBanndedSkill = GameConstants.bannedBindSkills(skill.getId());
|
||||
isBanndedSkill = GameConstants.bannedBindSkills(skill.getId());
|
||||
if (isBanndedSkill || (!c.getPlayer().isGM() && GameConstants.isGMSkills(skill.getId())) || (!GameConstants.isInJobTree(skill.getId(), c.getPlayer().getJob().getId()) && !c.getPlayer().isGM())) { //for those skills are are "technically" in the beginner tab, like bamboo rain in Dojo or skills you find in PYPQ
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit keymapping.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skill.getId() + "\r\n");
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().getSkillLevel(skill) < 1) {
|
||||
continue;
|
||||
}
|
||||
/* if (c.getPlayer().getSkillLevel(skill) < 1) { HOW WOULD A SKILL EVEN BE AVAILABLE TO KEYBINDING
|
||||
continue; IF THERE IS NOT EVEN A SINGLE POINT USED INTO IT??
|
||||
} */ //Nice to know some skills have the same ids as items, heh.
|
||||
}
|
||||
|
||||
c.getPlayer().changeKeybinding(key, new MapleKeyBinding(type, action));
|
||||
}
|
||||
} else if(mode == 1) { // Auto HP Potion
|
||||
|
||||
@@ -99,10 +99,10 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
|
||||
String name = slea.readMapleAsciiString();
|
||||
MapleCharacter invited = world.getPlayerStorage().getCharacterByName(name);
|
||||
if (invited != null) {
|
||||
if(invited.getLevel() < 10) { //min requirement is level 10
|
||||
c.announce(MaplePacketCreator.serverNotice(5, "The player you have invited does not meet the requirements."));
|
||||
return;
|
||||
}
|
||||
if(invited.getLevel() < 10) { //min requirement is level 10
|
||||
c.announce(MaplePacketCreator.serverNotice(5, "The player you have invited does not meet the requirements."));
|
||||
return;
|
||||
}
|
||||
if (invited.getParty() == null) {
|
||||
if (player.getParty() == null) {
|
||||
partyplayer = new MaplePartyCharacter(player);
|
||||
|
||||
@@ -245,8 +245,8 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
player.checkBerserk();
|
||||
player.expirationTask();
|
||||
//player.setRates();
|
||||
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
|
||||
player.createDragon();
|
||||
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
|
||||
player.createDragon();
|
||||
}
|
||||
if (newcomer){
|
||||
/*
|
||||
|
||||
@@ -59,18 +59,18 @@ public final class QuestActionHandler extends AbstractMaplePacketHandler {
|
||||
} else if (action == 4) { // scripted start quest
|
||||
int npc = slea.readInt();
|
||||
slea.readInt();
|
||||
if(quest.canStart(player, npc)) {
|
||||
QuestScriptManager.getInstance().start(c, questid, npc);
|
||||
}
|
||||
if(quest.canStart(player, npc)) {
|
||||
QuestScriptManager.getInstance().start(c, questid, npc);
|
||||
}
|
||||
} else if (action == 5) { // scripted end quests
|
||||
//System.out.println(slea.toString());
|
||||
int npc = slea.readInt();
|
||||
slea.readInt();
|
||||
|
||||
if(quest.canComplete(player, npc)) {
|
||||
QuestScriptManager.getInstance().end(c, questid, npc);
|
||||
player.getClient().getSession().write(MaplePacketCreator.showSpecialEffect(9)); //show effect when completion
|
||||
player.getMap().broadcastMessage(player, MaplePacketCreator.showForeignEffect(player.getId(), 9));//show effect around players I guess
|
||||
QuestScriptManager.getInstance().end(c, questid, npc);
|
||||
player.getClient().getSession().write(MaplePacketCreator.showSpecialEffect(9)); //show effect when completion
|
||||
player.getMap().broadcastMessage(player, MaplePacketCreator.showForeignEffect(player.getId(), 9));//show effect around players I guess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import net.server.channel.Channel;
|
||||
import net.server.guild.MapleGuild;
|
||||
import net.server.world.MapleParty;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import scripting.event.EventManager;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
import server.MapleInventoryManipulator;
|
||||
@@ -157,24 +158,19 @@ public class AbstractPlayerInteraction {
|
||||
return getClient().getEventManager(event);
|
||||
}
|
||||
|
||||
public void clearPQ(int toMap) {
|
||||
clearPQ(getWarpMap(toMap));
|
||||
}
|
||||
public EventInstanceManager getEventInstance() {
|
||||
return getPlayer().getEventInstance();
|
||||
}
|
||||
|
||||
public void clearPQ(MapleMap toMap) {
|
||||
if(getPlayer().getEventInstance() != null)
|
||||
getPlayer().getEventInstance().getEm().clearPQ(getPlayer().getEventInstance(), toMap);
|
||||
}
|
||||
|
||||
public MapleInventory getInventory(MapleInventoryType type) {
|
||||
return getPlayer().getInventory(type);
|
||||
}
|
||||
|
||||
public boolean hasItem(int itemid){
|
||||
public boolean hasItem(int itemid) {
|
||||
return haveItem(itemid, 1);
|
||||
}
|
||||
|
||||
public boolean hasItem(int itemid, int quantity){
|
||||
public boolean hasItem(int itemid, int quantity) {
|
||||
return haveItem(itemid, quantity);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@ import java.io.File;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
@@ -39,6 +41,7 @@ import javax.script.ScriptException;
|
||||
import net.server.world.MapleParty;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import server.MaplePortal;
|
||||
import server.TimerManager;
|
||||
import server.expeditions.MapleExpedition;
|
||||
import server.life.MapleMonster;
|
||||
@@ -52,6 +55,7 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -75,12 +79,23 @@ public class EventInstanceManager {
|
||||
private final WriteLock wL = mutex.writeLock();
|
||||
private ScheduledFuture<?> event_schedule = null;
|
||||
private boolean disposed = false;
|
||||
private boolean eventCleared = false;
|
||||
|
||||
// multi-leveled PQ rewards!
|
||||
private Map<Integer, List<Integer>> collectionSet = new HashMap<>(ServerConstants.MAX_EVENT_LEVELS);
|
||||
private Map<Integer, List<Integer>> collectionQty = new HashMap<>(ServerConstants.MAX_EVENT_LEVELS);
|
||||
private Map<Integer, Integer> collectionExp = new HashMap<>(ServerConstants.MAX_EVENT_LEVELS);
|
||||
|
||||
// Exp/Meso rewards by CLEAR on a stage
|
||||
private List<Integer> onMapClearExp = new ArrayList<>();
|
||||
private List<Integer> onMapClearMeso = new ArrayList<>();
|
||||
|
||||
// registers player status on an event (null on this Map structure equals to 0)
|
||||
private Map<Integer, Integer> playerGrid = new HashMap<>();
|
||||
|
||||
// registers all opened gates on the event. Will help late characters to encounter next stages gates already opened
|
||||
private Set<Integer> openedGates = new HashSet<>();
|
||||
|
||||
public EventInstanceManager(EventManager em, String name) {
|
||||
this.em = em;
|
||||
this.name = name;
|
||||
@@ -97,6 +112,8 @@ public class EventInstanceManager {
|
||||
}
|
||||
|
||||
public void giveEventPlayersExp(int gain, int mapId) {
|
||||
if(gain == 0) return;
|
||||
|
||||
rL.lock();
|
||||
try {
|
||||
if(mapId == -1) {
|
||||
@@ -113,6 +130,30 @@ public class EventInstanceManager {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void giveEventPlayersMeso(int gain) {
|
||||
giveEventPlayersMeso(gain, -1);
|
||||
}
|
||||
|
||||
public void giveEventPlayersMeso(int gain, int mapId) {
|
||||
if(gain == 0) return;
|
||||
|
||||
rL.lock();
|
||||
try {
|
||||
if(mapId == -1) {
|
||||
for(MapleCharacter mc: chars) {
|
||||
mc.gainMeso(gain * mc.getMesoRate());
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(MapleCharacter mc: chars) {
|
||||
if(mc.getMapId() == mapId) mc.gainMeso(gain * mc.getMesoRate());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerPlayer(MapleCharacter chr) {
|
||||
if (chr == null || !chr.isLoggedin()){
|
||||
@@ -186,12 +227,19 @@ public class EventInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelEventTimer() {
|
||||
if(event_schedule != null) event_schedule.cancel(false);
|
||||
public void stopEventTimer() {
|
||||
if(event_schedule != null) {
|
||||
event_schedule.cancel(false);
|
||||
event_schedule = null;
|
||||
}
|
||||
dismissEventTimer();
|
||||
}
|
||||
|
||||
private void dismissEventTimer() {
|
||||
for(MapleCharacter chr: getPlayers()) {
|
||||
chr.getClient().getSession().write(MaplePacketCreator.removeClock());
|
||||
}
|
||||
|
||||
event_schedule = null;
|
||||
eventTime = 0;
|
||||
timeStarted = 0;
|
||||
@@ -220,9 +268,10 @@ public class EventInstanceManager {
|
||||
public void unregisterPlayer(MapleCharacter chr) {
|
||||
wL.lock();
|
||||
try {
|
||||
chars.remove(chr);
|
||||
chars.remove(chr);
|
||||
gridRemove(chr);
|
||||
} finally {
|
||||
wL.unlock();
|
||||
wL.unlock();
|
||||
}
|
||||
|
||||
chr.setEventInstance(null);
|
||||
@@ -231,20 +280,20 @@ public class EventInstanceManager {
|
||||
public int getPlayerCount() {
|
||||
rL.lock();
|
||||
try {
|
||||
return chars.size();
|
||||
return chars.size();
|
||||
}
|
||||
finally {
|
||||
rL.unlock();
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public List<MapleCharacter> getPlayers() {
|
||||
rL.lock();
|
||||
try {
|
||||
return new ArrayList<>(chars);
|
||||
return new ArrayList<>(chars);
|
||||
}
|
||||
finally {
|
||||
rL.unlock();
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,37 +389,40 @@ public class EventInstanceManager {
|
||||
|
||||
public int getKillCount(MapleCharacter chr) {
|
||||
Integer kc = killCount.get(chr);
|
||||
if (kc == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return kc;
|
||||
}
|
||||
return (kc == null) ? 0 : kc;
|
||||
}
|
||||
|
||||
public void cancelSchedule() {
|
||||
if(event_schedule != null) {
|
||||
event_schedule.cancel(false);
|
||||
event_schedule = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
try {
|
||||
em.getIv().invokeFunction("dispose", this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
try {
|
||||
em.getIv().invokeFunction("dispose", this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
wL.lock();
|
||||
try {
|
||||
chars.clear();
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
|
||||
if(event_schedule != null) event_schedule.cancel(false);
|
||||
wL.lock();
|
||||
try {
|
||||
chars.clear();
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
|
||||
cancelSchedule();
|
||||
|
||||
mobs.clear();
|
||||
killCount.clear();
|
||||
mapFactory = null;
|
||||
if (expedition != null) {
|
||||
em.getChannelServer().getExpeditions().remove(expedition);
|
||||
}
|
||||
em.disposeInstance(name);
|
||||
em = null;
|
||||
mobs.clear();
|
||||
killCount.clear();
|
||||
mapFactory = null;
|
||||
if (expedition != null) {
|
||||
em.getChannelServer().getExpeditions().remove(expedition);
|
||||
}
|
||||
em.disposeInstance(name);
|
||||
em = null;
|
||||
}
|
||||
|
||||
public MapleMapFactory getMapFactory() {
|
||||
@@ -381,6 +433,8 @@ public class EventInstanceManager {
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(em == null) return;
|
||||
|
||||
try {
|
||||
em.getIv().invokeFunction(methodName, EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
@@ -431,8 +485,8 @@ public class EventInstanceManager {
|
||||
return props.getProperty(key);
|
||||
}
|
||||
|
||||
public Properties getProperties(){
|
||||
return props;
|
||||
public Properties getProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public void leftParty(MapleCharacter chr) {
|
||||
@@ -451,7 +505,7 @@ public class EventInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void finishPQ() {
|
||||
public void clearPQ() {
|
||||
try {
|
||||
em.getIv().invokeFunction("clearPQ", this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
@@ -472,149 +526,315 @@ public class EventInstanceManager {
|
||||
}
|
||||
|
||||
public final MapleMap setInstanceMap(final int mapid) { //gets instance map from the channelserv
|
||||
if (disposed) {
|
||||
if (disposed) {
|
||||
return this.getMapFactory().getMap(mapid);
|
||||
}
|
||||
mapIds.add(mapid);
|
||||
isInstanced.add(false);
|
||||
return this.getMapFactory().getMap(mapid);
|
||||
}
|
||||
mapIds.add(mapid);
|
||||
isInstanced.add(false);
|
||||
return this.getMapFactory().getMap(mapid);
|
||||
}
|
||||
|
||||
public final boolean disposeIfPlayerBelow(final byte size, final int towarp) {
|
||||
if (disposed) {
|
||||
return true;
|
||||
}
|
||||
MapleMap map = null;
|
||||
if (towarp > 0) {
|
||||
map = this.getMapFactory().getMap(towarp);
|
||||
}
|
||||
|
||||
rL.lock();
|
||||
try {
|
||||
if (chars != null && chars.size() < size) {
|
||||
for (MapleCharacter chr : chars) {
|
||||
if (chr == null) {
|
||||
continue;
|
||||
}
|
||||
unregisterPlayer(chr);
|
||||
if (towarp > 0) {
|
||||
chr.changeMap(map, map.getPortal(0));
|
||||
}
|
||||
}
|
||||
dispose();
|
||||
return true;
|
||||
if (disposed) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
return false;
|
||||
MapleMap map = null;
|
||||
if (towarp > 0) {
|
||||
map = this.getMapFactory().getMap(towarp);
|
||||
}
|
||||
|
||||
rL.lock();
|
||||
try {
|
||||
if (chars != null && chars.size() < size) {
|
||||
for (MapleCharacter chr : chars) {
|
||||
if (chr == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unregisterPlayer(chr);
|
||||
if (towarp > 0) {
|
||||
chr.changeMap(map, map.getPortal(0));
|
||||
}
|
||||
}
|
||||
|
||||
dispose();
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Integer> convertToIntegerArray(List<Double> list) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for(Double d: list) intList.add(d.intValue());
|
||||
|
||||
return intList;
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for(Double d: list) intList.add(d.intValue());
|
||||
|
||||
return intList;
|
||||
}
|
||||
|
||||
public void setEventClearStageExp(List<Double> gain) {
|
||||
onMapClearExp.clear();
|
||||
onMapClearExp.addAll(convertToIntegerArray(gain));
|
||||
}
|
||||
|
||||
public void setEventClearStageMeso(List<Double> gain) {
|
||||
onMapClearMeso.clear();
|
||||
onMapClearMeso.addAll(convertToIntegerArray(gain));
|
||||
}
|
||||
|
||||
public Integer getClearStageExp(int stage) { //stage counts from ONE.
|
||||
if(stage > onMapClearExp.size()) return 0;
|
||||
return onMapClearExp.get(stage - 1);
|
||||
}
|
||||
|
||||
public Integer getClearStageMeso(int stage) { //stage counts from ONE.
|
||||
if(stage > onMapClearMeso.size()) return 0;
|
||||
return onMapClearMeso.get(stage - 1);
|
||||
}
|
||||
|
||||
public List<Integer> getClearStageBonus(int stage) {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
list.add(getClearStageExp(stage));
|
||||
list.add(getClearStageMeso(stage));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public final void setEventRewards(List<Double> rwds, List<Double> qtys, int expGiven) {
|
||||
setEventRewards(1, rwds, qtys, expGiven);
|
||||
setEventRewards(1, rwds, qtys, expGiven);
|
||||
}
|
||||
|
||||
public final void setEventRewards(List<Double> rwds, List<Double> qtys) {
|
||||
setEventRewards(1, rwds, qtys);
|
||||
setEventRewards(1, rwds, qtys);
|
||||
}
|
||||
|
||||
public final void setEventRewards(int eventLevel, List<Double> rwds, List<Double> qtys) {
|
||||
setEventRewards(eventLevel, rwds, qtys, 0);
|
||||
setEventRewards(eventLevel, rwds, qtys, 0);
|
||||
}
|
||||
|
||||
public final void setEventRewards(int eventLevel, List<Double> rwds, List<Double> qtys, int expGiven) {
|
||||
// fixed EXP will be rewarded at the same time the random item is given
|
||||
|
||||
if(eventLevel <= 0 || eventLevel > ServerConstants.MAX_EVENT_LEVELS) return;
|
||||
eventLevel--; //event level starts from 1
|
||||
|
||||
List<Integer> rewardIds = convertToIntegerArray(rwds);
|
||||
List<Integer> rewardQtys = convertToIntegerArray(qtys);
|
||||
|
||||
//rewardsSet and rewardsQty hold temporary values
|
||||
collectionSet.put(eventLevel, rewardIds);
|
||||
collectionQty.put(eventLevel, rewardQtys);
|
||||
collectionExp.put(eventLevel, expGiven);
|
||||
// fixed EXP will be rewarded at the same time the random item is given
|
||||
|
||||
if(eventLevel <= 0 || eventLevel > ServerConstants.MAX_EVENT_LEVELS) return;
|
||||
eventLevel--; //event level starts from 1
|
||||
|
||||
List<Integer> rewardIds = convertToIntegerArray(rwds);
|
||||
List<Integer> rewardQtys = convertToIntegerArray(qtys);
|
||||
|
||||
//rewardsSet and rewardsQty hold temporary values
|
||||
wL.lock();
|
||||
try {
|
||||
collectionSet.put(eventLevel, rewardIds);
|
||||
collectionQty.put(eventLevel, rewardQtys);
|
||||
collectionExp.put(eventLevel, expGiven);
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private byte getRewardListRequirements(int level) {
|
||||
if(level >= collectionSet.size()) return 0;
|
||||
|
||||
byte rewardTypes = 0;
|
||||
List<Integer> list = collectionSet.get(level);
|
||||
|
||||
for (Integer itemId : list) {
|
||||
rewardTypes |= (1 << ItemConstants.getInventoryType(itemId).getType());
|
||||
}
|
||||
|
||||
return rewardTypes;
|
||||
if(level >= collectionSet.size()) return 0;
|
||||
|
||||
byte rewardTypes = 0;
|
||||
List<Integer> list = collectionSet.get(level);
|
||||
|
||||
for (Integer itemId : list) {
|
||||
rewardTypes |= (1 << ItemConstants.getInventoryType(itemId).getType());
|
||||
}
|
||||
|
||||
return rewardTypes;
|
||||
}
|
||||
|
||||
private boolean hasRewardSlot(MapleCharacter player, int eventLevel) {
|
||||
byte listReq = getRewardListRequirements(eventLevel); //gets all types of items present in the event reward list
|
||||
|
||||
//iterating over all valid inventory types
|
||||
for(byte type = 1; type <= 5; type++) {
|
||||
if((listReq >> type) % 2 == 1 && !player.hasEmptySlot(type))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
byte listReq = getRewardListRequirements(eventLevel); //gets all types of items present in the event reward list
|
||||
|
||||
//iterating over all valid inventory types
|
||||
for(byte type = 1; type <= 5; type++) {
|
||||
if((listReq >> type) % 2 == 1 && !player.hasEmptySlot(type))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean giveEventReward(MapleCharacter player) {
|
||||
return giveEventReward(player, 1);
|
||||
return giveEventReward(player, 1);
|
||||
}
|
||||
|
||||
//gives out EXP & a random item in a similar fashion of when clearing KPQ, LPQ, etc.
|
||||
public final boolean giveEventReward(MapleCharacter player, int eventLevel) {
|
||||
eventLevel--; //event level starts counting from 1
|
||||
if(eventLevel >= collectionSet.size()) return true;
|
||||
|
||||
List<Integer> rewardsSet = collectionSet.get(eventLevel);
|
||||
List<Integer> rewardsQty = collectionQty.get(eventLevel);
|
||||
|
||||
Integer rewardExp = collectionExp.get(eventLevel);
|
||||
if(rewardExp == null) rewardExp = 0;
|
||||
|
||||
if(rewardsSet == null || rewardsSet.isEmpty()) {
|
||||
if(rewardExp > 0) player.gainExp(rewardExp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!hasRewardSlot(player, eventLevel)) return false;
|
||||
rL.lock();
|
||||
try {
|
||||
eventLevel--; //event level starts counting from 1
|
||||
if(eventLevel >= collectionSet.size()) return true;
|
||||
|
||||
AbstractPlayerInteraction api = new AbstractPlayerInteraction(player.getClient());
|
||||
int rnd = (int)Math.floor(Math.random() * rewardsSet.size());
|
||||
|
||||
api.gainItem(rewardsSet.get(rnd), rewardsQty.get(rnd).shortValue());
|
||||
if(rewardExp > 0) player.gainExp(rewardExp);
|
||||
return true;
|
||||
List<Integer> rewardsSet = collectionSet.get(eventLevel);
|
||||
List<Integer> rewardsQty = collectionQty.get(eventLevel);
|
||||
|
||||
Integer rewardExp = collectionExp.get(eventLevel);
|
||||
if(rewardExp == null) rewardExp = 0;
|
||||
|
||||
if(rewardsSet == null || rewardsSet.isEmpty()) {
|
||||
if(rewardExp > 0) player.gainExp(rewardExp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!hasRewardSlot(player, eventLevel)) return false;
|
||||
|
||||
AbstractPlayerInteraction api = new AbstractPlayerInteraction(player.getClient());
|
||||
int rnd = (int)Math.floor(Math.random() * rewardsSet.size());
|
||||
|
||||
api.gainItem(rewardsSet.get(rnd), rewardsQty.get(rnd).shortValue());
|
||||
if(rewardExp > 0) player.gainExp(rewardExp);
|
||||
return true;
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final void setEventCleared() {
|
||||
eventCleared = true;
|
||||
}
|
||||
|
||||
public final boolean isEventTeamLackingNow(boolean testLeader, int minPlayers, MapleCharacter quitter) {
|
||||
if(eventCleared && getPlayerCount() > 1) return false;
|
||||
|
||||
if(!eventCleared && testLeader && getLeader().getId() == quitter.getId()) return true;
|
||||
if(getPlayerCount() <= minPlayers) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public final boolean isEventTeamTogether() {
|
||||
if(chars.size() <= 1) return true;
|
||||
|
||||
int mapId = chars.get(0).getMapId();
|
||||
for(int i = 1; i < chars.size(); i++) {
|
||||
if(chars.get(i).getMapId() != mapId) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
rL.lock();
|
||||
try {
|
||||
if(chars.size() <= 1) return true;
|
||||
|
||||
int mapId = chars.get(0).getMapId();
|
||||
for(int i = 1; i < chars.size(); i++) {
|
||||
if(chars.get(i).getMapId() != mapId) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final void warpEventTeam(int warpTo) {
|
||||
for (MapleCharacter chr : chars) {
|
||||
chr.changeMap(warpTo);
|
||||
}
|
||||
rL.lock();
|
||||
try {
|
||||
for (MapleCharacter chr : chars) {
|
||||
chr.changeMap(warpTo);
|
||||
}
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final MapleCharacter getLeader() {
|
||||
rL.lock();
|
||||
try {
|
||||
for (MapleCharacter chr : chars) {
|
||||
if(chr.isPartyLeader()) return chr;
|
||||
}
|
||||
|
||||
return null;
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final void showWrongEffect() {
|
||||
MapleMap map = getMapInstance(getLeader().getMapId());
|
||||
map.broadcastMessage(MaplePacketCreator.showEffect("quest/party/wrong_kor"));
|
||||
map.broadcastMessage(MaplePacketCreator.playSound("Party1/Failed"));
|
||||
}
|
||||
|
||||
public final void showClearEffect() {
|
||||
showClearEffect(false);
|
||||
}
|
||||
|
||||
public final void showClearEffect(boolean hasGate) {
|
||||
MapleMap map = getMapInstance(getLeader().getMapId());
|
||||
map.broadcastMessage(MaplePacketCreator.showEffect("quest/party/clear"));
|
||||
map.broadcastMessage(MaplePacketCreator.playSound("Party1/Clear"));
|
||||
if(hasGate) {
|
||||
map.broadcastMessage(MaplePacketCreator.environmentChange("gate", 2));
|
||||
wL.lock();
|
||||
try {
|
||||
openedGates.add(map.getId());
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void recoverOpenedGate(MapleCharacter chr, int thisMapId) {
|
||||
rL.lock();
|
||||
try {
|
||||
if(openedGates.contains(thisMapId)) {
|
||||
chr.announce(MaplePacketCreator.environmentChange("gate", 2));
|
||||
}
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final void linkToNextStage(int thisStage, String eventFamily, int thisMapId) {
|
||||
List<Integer> list = getClearStageBonus(thisStage); // will give bonus exp & mesos to everyone in the event
|
||||
giveEventPlayersExp(list.get(0));
|
||||
giveEventPlayersMeso(list.get(1));
|
||||
|
||||
thisStage--; //stages counts from ONE, scripts from ZERO
|
||||
|
||||
MapleMap nextStage = getMapInstance(thisMapId);
|
||||
MaplePortal portal = nextStage.getPortal("next00");
|
||||
if (portal != null) {
|
||||
portal.setScriptName(eventFamily + thisStage);
|
||||
}
|
||||
}
|
||||
|
||||
// registers a player status in an event
|
||||
public final void gridInsert(MapleCharacter chr, int newStatus) {
|
||||
wL.lock();
|
||||
try {
|
||||
playerGrid.put(chr.getId(), newStatus);
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// unregisters a player status in an event
|
||||
public final void gridRemove(MapleCharacter chr) {
|
||||
wL.lock();
|
||||
try {
|
||||
playerGrid.remove(chr.getId());
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// checks a player status
|
||||
public final int gridCheck(MapleCharacter chr) {
|
||||
rL.lock();
|
||||
try {
|
||||
Integer i = playerGrid.get(chr.getId());
|
||||
return (i != null) ? i : -1;
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final void gridClear() {
|
||||
wL.lock();
|
||||
try {
|
||||
playerGrid.clear();
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,56 +154,76 @@ public class EventManager {
|
||||
}
|
||||
|
||||
//Expedition method: starts an expedition
|
||||
public void startInstance(MapleExpedition exped) {
|
||||
public boolean startInstance(MapleExpedition exped) {
|
||||
try {
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
|
||||
if(eim == null) return false;
|
||||
|
||||
eim.registerExpedition(exped);
|
||||
exped.start();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Regular method: player
|
||||
public void startInstance(MapleCharacter chr) {
|
||||
public boolean startInstance(MapleCharacter chr) {
|
||||
try {
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
|
||||
if(eim == null) return false;
|
||||
|
||||
eim.registerPlayer(chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//PQ method: starts a PQ
|
||||
public void startInstance(MapleParty party, MapleMap map) {
|
||||
public boolean startInstance(MapleParty party, MapleMap map) {
|
||||
try {
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
|
||||
if(eim == null) return false;
|
||||
|
||||
eim.registerParty(party, map);
|
||||
party.setEligibleMembers(null);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//PQ method: starts a PQ with a difficulty level, requires function setup(difficulty, leaderid) instead of setup()
|
||||
public void startInstance(MapleParty party, MapleMap map, int difficulty) {
|
||||
public boolean startInstance(MapleParty party, MapleMap map, int difficulty) {
|
||||
try {
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, party.getLeader().getId()));
|
||||
if(eim == null) return false;
|
||||
|
||||
eim.registerParty(party, map);
|
||||
party.setEligibleMembers(null);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//non-PQ method for starting instance
|
||||
public void startInstance(EventInstanceManager eim, String leader) {
|
||||
public boolean startInstance(EventInstanceManager eim, String leader) {
|
||||
try {
|
||||
if(eim == null) return false;
|
||||
|
||||
iv.invokeFunction("setup", eim);
|
||||
eim.setProperty("leader", leader);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<MaplePartyCharacter> getEligibleParty(MapleParty party) {
|
||||
@@ -225,6 +245,14 @@ public class EventManager {
|
||||
return(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void clearPQ(EventInstanceManager eim) {
|
||||
try {
|
||||
iv.invokeFunction("clearPQ", eim);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearPQ(EventInstanceManager eim, MapleMap toMap) {
|
||||
try {
|
||||
iv.invokeFunction("clearPQ", eim, toMap);
|
||||
|
||||
@@ -227,7 +227,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
||||
if (gain > 0 && ServerConstants.USE_AUTOBAN == true) {
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " gained " + gain + " mesos from NPC " + npc + "\r\n");
|
||||
}
|
||||
getPlayer().gainMeso(gain, true, false, true);
|
||||
getPlayer().gainMeso(gain);
|
||||
}
|
||||
|
||||
public void gainExp(int gain) {
|
||||
|
||||
@@ -90,8 +90,8 @@ public class MapleQuest {
|
||||
|
||||
MapleQuestRequirement req = this.getRequirement(type, startReq);
|
||||
|
||||
if(req == null)
|
||||
continue;
|
||||
if(req == null)
|
||||
continue;
|
||||
|
||||
if (type.equals(MapleQuestRequirementType.MOB)) {
|
||||
for (MapleData mob : startReq.getChildren()) {
|
||||
@@ -161,15 +161,46 @@ public class MapleQuest {
|
||||
public static MapleQuest getInstance(int id) {
|
||||
MapleQuest ret = quests.get(id);
|
||||
if (ret == null) {
|
||||
questInfo = questData.getData("QuestInfo.img");
|
||||
questReq = questData.getData("Check.img");
|
||||
questAct = questData.getData("Act.img");
|
||||
questInfo = questData.getData("QuestInfo.img");
|
||||
questReq = questData.getData("Check.img");
|
||||
questAct = questData.getData("Act.img");
|
||||
|
||||
ret = new MapleQuest(id);
|
||||
quests.put(id, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private String getIntervalTimeLeft(MapleCharacter c, IntervalRequirement r) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
long futureTime = c.getQuest(MapleQuest.getInstance(getId())).getCompletionTime() + r.getInterval();
|
||||
long leftTime = futureTime - System.currentTimeMillis();
|
||||
|
||||
byte mode = 0;
|
||||
if(leftTime / (60*1000) > 0) {
|
||||
mode++; //counts minutes
|
||||
|
||||
if(leftTime / (60*60*1000) > 0)
|
||||
mode++; //counts hours
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case 2:
|
||||
int hours = (int) ((leftTime / (1000*60*60)));
|
||||
str.append(hours + " hours, ");
|
||||
|
||||
case 1:
|
||||
int minutes = (int) ((leftTime / (1000*60)) % 60);
|
||||
str.append(minutes + " minutes, ");
|
||||
|
||||
default:
|
||||
int seconds = (int) (leftTime / 1000) % 60 ;
|
||||
str.append(seconds + " seconds");
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public boolean canStart(MapleCharacter c, int npcid) {
|
||||
if (c.getQuest(this).getStatus() != Status.NOT_STARTED && !(c.getQuest(this).getStatus() == Status.COMPLETED && repeatable)) {
|
||||
@@ -177,6 +208,9 @@ public class MapleQuest {
|
||||
}
|
||||
for (MapleQuestRequirement r : startReqs.values()) {
|
||||
if (!r.check(c, npcid)) {
|
||||
if(r.getType().getType() == MapleQuestRequirementType.INTERVAL.getType()) {
|
||||
c.message("This quest will become available again in approximately " + getIntervalTimeLeft(c, (IntervalRequirement)r) + ".");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -198,9 +232,9 @@ public class MapleQuest {
|
||||
public void start(MapleCharacter c, int npc) {
|
||||
if (autoStart || canStart(c, npc)) {
|
||||
for (MapleQuestAction a : startActs.values()) {
|
||||
if (!a.check(c, null)) { // would null be good ?
|
||||
return;
|
||||
}
|
||||
if (!a.check(c, null)) { // would null be good ?
|
||||
return;
|
||||
}
|
||||
a.run(c, null);
|
||||
}
|
||||
forceStart(c, npc);
|
||||
@@ -212,20 +246,20 @@ public class MapleQuest {
|
||||
}
|
||||
|
||||
public void complete(MapleCharacter c, int npc, Integer selection) {
|
||||
if (autoPreComplete || canComplete(c, npc)) {
|
||||
for (MapleQuestAction a : completeActs.values()) {
|
||||
if (!a.check(c, selection)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
forceComplete(c, npc);
|
||||
for (MapleQuestAction a : completeActs.values()) {
|
||||
a.run(c, selection);
|
||||
}
|
||||
|
||||
c.getClient().getSession().write(MaplePacketCreator.showSpecialEffect(9)); // Quest completion
|
||||
c.getMap().broadcastMessage(c, MaplePacketCreator.showForeignEffect(c.getId(), 9), false); //use 9 instead of 12 for both
|
||||
}
|
||||
if (autoPreComplete || canComplete(c, npc)) {
|
||||
for (MapleQuestAction a : completeActs.values()) {
|
||||
if (!a.check(c, selection)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
forceComplete(c, npc);
|
||||
for (MapleQuestAction a : completeActs.values()) {
|
||||
a.run(c, selection);
|
||||
}
|
||||
|
||||
c.getClient().getSession().write(MaplePacketCreator.showSpecialEffect(9)); // Quest completion
|
||||
c.getMap().broadcastMessage(c, MaplePacketCreator.showForeignEffect(c.getId(), 9), false); //use 9 instead of 12 for both
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(MapleCharacter c) {
|
||||
@@ -314,9 +348,9 @@ public class MapleQuest {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int getTimeLimit() {
|
||||
return timeLimit;
|
||||
}
|
||||
public int getTimeLimit() {
|
||||
return timeLimit;
|
||||
}
|
||||
|
||||
public static void clearCache(int quest) {
|
||||
if(quests.containsKey(quest)){
|
||||
|
||||
@@ -42,6 +42,9 @@ public class IntervalRequirement extends MapleQuestRequirement {
|
||||
questID = quest.getId();
|
||||
}
|
||||
|
||||
public int getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processData(MapleData data) {
|
||||
|
||||
@@ -51,6 +51,6 @@ public abstract class MapleQuestRequirement {
|
||||
public abstract void processData(MapleData data);
|
||||
|
||||
public MapleQuestRequirementType getType() {
|
||||
return type;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -2508,6 +2508,7 @@ public class MaplePacketCreator {
|
||||
* @param progress
|
||||
* @return
|
||||
*/
|
||||
|
||||
public static byte[] updateQuestInfo(short quest, int npc) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue());
|
||||
|
||||
Reference in New Issue
Block a user