Persistent diseases + PQ request system + GuildPQ fix

Implemented persistent diseases. Players now keep their disease status when logging out the game.
Solved several concurrent access issues in MapleMap and MapleMonster.
Implemented an option where an account's character slots can be accounted either by each world or all-server range.
Fixed some issues with character slot count when entering/exiting Cash Shop.
Fixed an exploit with Papulatus, on where players could create cracks of dimension infinitely.
Solved an issue with the "reach" command not working properly when the targeted player is on an event instance.
Devised an advanced and secure "PQ request" system. The service revolves around expecting massive number of players requesting a "pass" simultaneously, and fairly & swiftly responsing as much people as possible.
Improved overall Whisper handler performance.
Fixed GPQ Stage 1 statues not working as expected, which rendered the instance unplayable until now.
Added commands for start, complete and reset quests.
This commit is contained in:
ronancpl
2018-08-18 11:38:55 -03:00
parent cda4433d99
commit 0d47edf1a7
116 changed files with 1596 additions and 703 deletions
+1 -1
View File
@@ -59,7 +59,7 @@ Although development is halted, support for fixing features that were implemente
If you liked this project, please don't forget to __star__ the repo ;) . If you liked this project, please don't forget to __star__ the repo ;) .
It's never too much to tell this, even still thanks to everyone that have been contributing something for the continuous improvement of the server! Be it through bug reports, donation, code snippets and/or pull requests. It's never enough to tell this, thanks to everyone that have been contributing something for the continuous improvement of the server! Be it through bug reports, donation, code snippets and/or pull requests.
Our Discord channel is still available on: https://discord.gg/Q7wKxHX Our Discord channel is still available on: https://discord.gg/Q7wKxHX
+3
View File
@@ -116,6 +116,7 @@ Monsters, Maps & Reactors:
PQ potentials: PQ potentials:
* Advanced synchronization and smart management of the PQ registration system, as expected for a core server mechanic that is largely used by the players.
* Lobby system - Multiple PQ instances on same channel. * Lobby system - Multiple PQ instances on same channel.
* Expedition system - Multiples parties can attempt on a same instance (lobbies and expeds are mutually-exclusive). * Expedition system - Multiples parties can attempt on a same instance (lobbies and expeds are mutually-exclusive).
* Guild queue system - Guilds can register themselves on a queue for the GPQ. * Guild queue system - Guilds can register themselves on a queue for the GPQ.
@@ -129,6 +130,7 @@ Player potentials:
* Gain fame by quests. * Gain fame by quests.
* Pet evolutions functional (not GMS-like). * Pet evolutions functional (not GMS-like).
* Reviewed keybinding system. * Reviewed keybinding system.
* Account's Character slots: either each world has it's own count or there's a shared value between all worlds.
Server potentials: Server potentials:
@@ -147,6 +149,7 @@ Server potentials:
* Pet item pickup now gives preference to player attacks rather than forcing attack disables when automatically picking up. * Pet item pickup now gives preference to player attacks rather than forcing attack disables when automatically picking up.
* Channel capacity bar functional and world servers with max capacity checks. * Channel capacity bar functional and world servers with max capacity checks.
* Disease status are now visible for other players, even when changing maps. * Disease status are now visible for other players, even when changing maps.
* Players keep their current disease status saved when exiting the game, returning with them on login.
* Poison damage value are now visible for other players. * Poison damage value are now visible for other players.
* Mastery book announcer displays droppers of needed books of a player, by reading underlying DB. * Mastery book announcer displays droppers of needed books of a player, by reading underlying DB.
* Custom jail system (needs provided custom wz). * Custom jail system (needs provided custom wz).
+21 -1
View File
@@ -1226,4 +1226,24 @@ Modificado algumas tabelas em ThreadTracker e World para usar Integer ao invés
07 Agosto 2018, 07 Agosto 2018,
Corrigido um bug na fase de login que nao construia corretamente overview de characters sem itens equipados, lancando excecoes posteriormente. Corrigido um bug na fase de login que nao construia corretamente overview de characters sem itens equipados, lancando excecoes posteriormente.
Revisado alguns casos de borda com doors levando as mesmas a nao sumirem imediatamente em certos cenarios. Revisado alguns casos de borda com doors levando as mesmas a nao sumirem imediatamente em certos cenarios.
08 - 10 Agosto 2018,
Adicionado registro de diseases na DB. Agora jogadores continuam com diseases ao voltar a logar no jogo.
Corrigido exploit com jogadores podendo visitar sua propria loja via owl.
Corrigido varios problemas de acesso concorrente e deadlocks em recursos do MapleMap e MapleMonster.
Implementado character slots para cobrir limite de personagens por conta (ao inves de 3 em cada mundo).
Corrigido diversos problemas com character slots ao entrar/sair do cash shop (erro ligado a alternancia de MapleClients).
Corrigido exploit com quest de Papulatus, onde jogadores poderiam gerar cracks of dimension por desistir de quests.
Corrigido jogadores podendo ser registrados em event instances mesmo quando estas ja estao liberadas (disposed).
Corrigido comando "reach" nao funcionando corretamente para casos que envolvam event instances.
Implementado um sistema avancado e seguro de escalonamento de requisicoes delegadas com iniciar nova PQs.
13 - 14 Agosto 2018,
Corrigido quest "Revealed Identity" erroneamente requisitando itens de quest anteriores de jogadores, impossibilitando jogadores de comecar quests em certos casos.
Melhorado handler de whisper, agora buscando referencias a DB somente em casos onde o jogador eh GM.
Retirado campo de GM da tabela "accounts".
Corrigido estatuas do stage1 da GuildPQ nao funcionando corretamente.
Alterado varias strings de NPCs e de mensagens utilizando a palavra "evento" querendo dizer instancias (julgamento subjetivo).
Adicionado comandos para start, complete e reset quests.
Adicionado scripts para meteoritos de Omega Sector.
+4 -4
View File
@@ -30,10 +30,10 @@ endorsed.classpath=
excludes= excludes=
file.reference.HikariCP-java7-2.4.12.jar=cores/HikariCP-java7-2.4.12.jar file.reference.HikariCP-java7-2.4.12.jar=cores/HikariCP-java7-2.4.12.jar
file.reference.MapleSolaxia-src=src file.reference.MapleSolaxia-src=src
file.reference.mina-core-2.0.7.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\mina-core-2.0.7.jar file.reference.mina-core-2.0.7.jar=cores\\mina-core-2.0.7.jar
file.reference.mysql-connector-java-bin.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\mysql-connector-java-bin.jar file.reference.mysql-connector-java-bin.jar=cores\\mysql-connector-java-bin.jar
file.reference.slf4j-api-1.6.6.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\slf4j-api-1.6.6.jar file.reference.slf4j-api-1.6.6.jar=cores\\slf4j-api-1.6.6.jar
file.reference.slf4j-jdk14-1.7.5.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\slf4j-jdk14-1.7.5.jar file.reference.slf4j-jdk14-1.7.5.jar=cores\\slf4j-jdk14-1.7.5.jar
includes=** includes=**
jar.archive.disabled=${jnlp.enabled} jar.archive.disabled=${jnlp.enabled}
jar.compress=true jar.compress=true
+3 -3
View File
@@ -247,7 +247,7 @@ function changedMap(eim, player, mapid) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} else { } else {
@@ -303,7 +303,7 @@ function playerRevive(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -315,7 +315,7 @@ function playerDisconnected(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
+1 -1
View File
@@ -236,7 +236,7 @@ function changedMap(eim, player, mapid) {
function afterChangedMap(eim, player, mapid) { function afterChangedMap(eim, player, mapid) {
if (mapid == 990000100) { if (mapid == 990000100) {
var texttt = "So, here is the brief. You guys should be warned that, once out on the fortress outskirts, anyone that would not be equipping the #b#t1032033##k will die instantly due to the deteriorated state of the air around there. That being said, once your team moves out to the next stage, make sure to #bhit the glowing rocks#k in that region and #bequip the dropped item#k before advancing stages. That will protect you thoroughly from the air sickness. Good luck!"; var texttt = "So, here is the brief. You guys should be warned that, once out on the fortress outskirts, anyone that would not be equipping the #b#t1032033##k will die instantly due to the deteriorated state of the air around there. That being said, once your team moves out, make sure to #bhit the glowing rocks#k in that region and #bequip the dropped item#k before advancing stages. That will protect you thoroughly from the air sickness. Good luck!";
player.getClient().getSession().write(Packages.tools.MaplePacketCreator.getNPCTalk(9040000, /*(byte)*/ 0, texttt, "00 00", /*(byte)*/ 0)); player.getClient().getSession().write(Packages.tools.MaplePacketCreator.getNPCTalk(9040000, /*(byte)*/ 0, texttt, "00 00", /*(byte)*/ 0));
} }
} }
+3 -3
View File
@@ -132,7 +132,7 @@ function changedMap(eim, player, mapid) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -149,7 +149,7 @@ function playerRevive(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -161,7 +161,7 @@ function playerDisconnected(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
+3 -3
View File
@@ -118,7 +118,7 @@ function changedMap(eim, player, mapid) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -135,7 +135,7 @@ function playerRevive(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -147,7 +147,7 @@ function playerDisconnected(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
+3 -3
View File
@@ -125,7 +125,7 @@ function changedMap(eim, player, mapid) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -144,7 +144,7 @@ function playerRevive(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -156,7 +156,7 @@ function playerDisconnected(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
+3 -3
View File
@@ -120,7 +120,7 @@ function changedMap(eim, player, mapid) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -137,7 +137,7 @@ function playerRevive(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
@@ -149,7 +149,7 @@ function playerDisconnected(eim, player) {
end(eim); end(eim);
} }
else { else {
eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the event."); eim.dropMessage(5, "[Expedition] " + player.getName() + " has left the instance.");
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} }
} }
+2 -2
View File
@@ -58,7 +58,7 @@ function action(mode, type, selection) {
return; return;
} }
cm.sendSimple("#e#b<Party Quest: Primrose Hill>\r\n#k#n" + em.getProperty("party") + "\r\n\r\nI'm Tory. Inside here is a beautiful hill where the primrose blooms. There's a tiger that lives in the hill, Growlie, and he seems to be looking for something to eat. Would you like to head over to the hill of primrose and join forces with your party members to help Growlie out?#b\r\n#L0#I want to participate in the party quest.\r\n#L1#I want to find party members.\r\n#L2#I would like to hear more details.\r\n#L3#I would like to redeem an event hat."); cm.sendSimple("#e#b<Party Quest: Primrose Hill>\r\n#k#n" + em.getProperty("party") + "\r\n\r\nI'm Tory. Inside here is a beautiful hill where the primrose blooms. There's a tiger that lives in the hill, Growlie, and he seems to be looking for something to eat. Would you like to head over to the hill of primrose and join forces with your party members to help Growlie out?#b\r\n#L0#I want to participate in the party quest.\r\n#L1#I want to find party members.\r\n#L2#I would like to hear more details.\r\n#L3#I would like to redeem an instance hat.");
} else if (status == 1) { } else if (status == 1) {
if (selection == 0) { if (selection == 0) {
if (cm.getParty() == null) { if (cm.getParty() == null) {
@@ -87,7 +87,7 @@ function action(mode, type, selection) {
cm.sendOk("#e#b<Party Quest: Primrose Hill>#k#n\r\nCollect primrose seeds from the flowers at the bottom part of the map and drop them by the platforms above the stage. Primrose seed color must match to grow the seeds, so test until you find the correct combination. When all the seeds have been planted, that is, starting second part of the mission, scout the Moon Bunny while it prepares Rice Cakes for the hungry Growlie. Once Growlie becomes satisfied, your mission is complete."); cm.sendOk("#e#b<Party Quest: Primrose Hill>#k#n\r\nCollect primrose seeds from the flowers at the bottom part of the map and drop them by the platforms above the stage. Primrose seed color must match to grow the seeds, so test until you find the correct combination. When all the seeds have been planted, that is, starting second part of the mission, scout the Moon Bunny while it prepares Rice Cakes for the hungry Growlie. Once Growlie becomes satisfied, your mission is complete.");
cm.dispose(); cm.dispose();
} else { } else {
cm.sendYesNo("So you want to exchange #b20 #b#t4001158##k for the event-designed hat?"); cm.sendYesNo("So you want to exchange #b20 #b#t4001158##k for the instance-designed hat?");
} }
} else { } else {
if(cm.hasItem(4001158, 20)) { if(cm.hasItem(4001158, 20)) {
+9 -11
View File
@@ -22,18 +22,16 @@ function action(mode, type, selection) {
cm.sendOk("This training ground is available only for those under level 20."); cm.sendOk("This training ground is available only for those under level 20.");
cm.dispose(); cm.dispose();
return; return;
} } else if (cm.isQuestActive(22515) || cm.isQuestActive(22516) || cm.isQuestActive(22517) || cm.isQuestActive(22518)) {
cm.sendYesNo("Would you like to go in the special Training Center?");
if (cm.isQuestActive(22515) || cm.isQuestActive(22516) || cm.isQuestActive(22517) || cm.isQuestActive(22518)) {
cm.sendYesNo("Would you like to go in the special Spore Training Center?");
status = 1; status = 1;
} } else {
var selStr = "Would you like to go into the Training Center?";
var selStr = "Would you like to go into the Training Center?"; for (var i = 0; i < num; i++) {
for (var i = 0; i < num; i++) { selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k"; }
} cm.sendSimple(selStr);
cm.sendSimple(selStr); }
} else if (status == 1) { } else if (status == 1) {
if (selection < 0 || selection >= num) { if (selection < 0 || selection >= num) {
cm.dispose(); cm.dispose();
+8 -13
View File
@@ -22,21 +22,16 @@ function action(mode, type, selection) {
cm.sendOk("This training ground is available only for those under level 20."); cm.sendOk("This training ground is available only for those under level 20.");
cm.dispose(); cm.dispose();
return; return;
} } else if (cm.isQuestActive(22515) || cm.isQuestActive(22516) || cm.isQuestActive(22517) || cm.isQuestActive(22518)) {
else if (cm.isQuestActive(22515) || cm.isQuestActive(22516) || cm.isQuestActive(22517) || cm.isQuestActive(22518)) {
cm.sendYesNo("Would you like to enter the special Training Center?"); cm.sendYesNo("Would you like to enter the special Training Center?");
status = 1; status = 1;
} } else {
var selStr = "Would you like to go into the Training Center?";
else { for (var i = 0; i < num; i++) {
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
var selStr = "Would you like to go into the Training Center?"; }
for (var i = 0; i < num; i++) { cm.sendSimple(selStr);
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k"; }
}
cm.sendSimple(selStr);
}
} else if (status == 1) { } else if (status == 1) {
if (selection < 0 || selection >= num) { if (selection < 0 || selection >= num) {
+1 -1
View File
@@ -20,7 +20,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* Shane 1032004 /* Shane 1032004
* By Moogra * @Author Moogra
*/ */
function start() { function start() {
+2 -2
View File
@@ -61,10 +61,10 @@ function action(mode, type, selection) {
cm.dispose(); cm.dispose();
return; return;
} else { } else {
cm.sendYesNo("Your team must collect #r" + couponsNeeded + "#k coupons to complete this event. Talk to me when you have the right amount in hands... Or you want to #bquit now#k? Note that if you quit now #ryour team will be forced to quit#k as well."); cm.sendYesNo("Your team must collect #r" + couponsNeeded + "#k coupons to complete this instance. Talk to me when you have the right amount in hands... Or you want to #bquit now#k? Note that if you quit now #ryour team will be forced to quit#k as well.");
} }
} else { } else {
cm.sendYesNo("Your team must collect #r" + couponsNeeded + "#k coupons to complete this event. Let your leader talk to me with the right amount in hands... Or you want to #bquit now#k? Note that if you quit now your team #rmay become undermanned#k to complete this event."); cm.sendYesNo("Your team must collect #r" + couponsNeeded + "#k coupons to complete this instance. Let your leader talk to me with the right amount in hands... Or you want to #bquit now#k? Note that if you quit now your team #rmay become undermanned#k to further continue this instance.");
} }
} else { } else {
if(!eim.giveEventReward(cm.getPlayer())) { if(!eim.giveEventReward(cm.getPlayer())) {
+1 -1
View File
@@ -25,7 +25,7 @@ function start() {
var eli = em.getEligibleParty(cm.getParty()); var eli = em.getEligibleParty(cm.getParty());
if(eli.size() > 0) { if(eli.size() > 0) {
if(!em.startInstance(cm.getParty(), cm.getPlayer().getMap(), 1)) { if(!em.startInstance(cm.getParty(), cm.getPlayer().getMap(), 1)) {
cm.sendOk("A party in your name is already registered in this event."); cm.sendOk("A party in your name is already registered in this instance.");
} }
} else { } else {
cm.sendOk("You cannot start this party quest yet, because either your party is not in the range size, some of your party members are not eligible to attempt it or they are not in this map. If you're having trouble finding party members, try Party Search."); cm.sendOk("You cannot start this party quest yet, because either your party is not in the range size, some of your party members are not eligible to attempt it or they are not in this map. If you're having trouble finding party members, try Party Search.");
+1 -1
View File
@@ -24,7 +24,7 @@
* @ID: 1103005 * @ID: 1103005
* @Map Id: 913040006 * @Map Id: 913040006
* @Function: Cygnus Creator * @Function: Cygnus Creator
* @Author Jay (text) * @Author Jay <text>
* @Author David * @Author David
*/ */
+1 -1
View File
@@ -20,7 +20,7 @@
*/ */
/*Adobis /*Adobis
* *
*@author SharpAceX (Alan) *@author Alan (SharpAceX)
*@author Ronan *@author Ronan
*/ */
importPackage(Packages.server.expeditions); importPackage(Packages.server.expeditions);
+2 -2
View File
@@ -20,7 +20,7 @@
*/ */
/* /*
* @Authors Stereo, xQuasar, <<XkelvinchiaX@Kelvin(For make it Fully Working.)>> * @Author Stereo, xQuasar, <<XkelvinchiaX@Kelvin(For make it Fully Working.)>>
* *
* Adobis - El Nath: Entrance to Zakum Altar (211042400) * Adobis - El Nath: Entrance to Zakum Altar (211042400)
* *
@@ -80,7 +80,7 @@ function action(mode, type, selection) {
else { // start Zakum Battle else { // start Zakum Battle
var eim = em.newInstance("Zakum" + passwd); var eim = em.newInstance("Zakum" + passwd);
if(!em.startInstance(eim,cm.getPlayer().getName())) { if(!em.startInstance(eim,cm.getPlayer().getName())) {
cm.sendOk("A party in your name is already registered in this event."); cm.sendOk("A party in your name is already registered in this instance.");
cm.dispose(); cm.dispose();
return; return;
} }
+127 -126
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn(MapleSea Like)(Need to add creation of minigame) /* Author: aaroncsn <(MapleSea Like)(Need to add creation of minigame)>
NPC Name: Wisp NPC Name: Wisp
Map(s): Ludibrium: Eos Tower Entrance(220000400) Map(s): Ludibrium: Eos Tower Entrance(220000400)
Description: Pet Master Description: Pet Master
@@ -12,130 +12,131 @@ function start() {
function action(mode, type, selection) { function action(mode, type, selection) {
if (mode == -1) { if (mode == -1) {
cm.dispose();
} else {
if (status >= 0 && mode == 0) {
cm.dispose(); cm.dispose();
return; } else {
} if (status >= 0 && mode == 0) {
if (mode == 1) cm.dispose();
status++; return;
else }
status--; if (mode == 1)
if(status == 0){ status++;
cm.sendSimple("Hello there, I'm #bMar the Fairy#k of Victoria Island's main disciple. Mar the Fairy summoned me here to see if the pets are being taken care of here in Ludibrium. What can I do for you? \r\n#L0##bMy pet has turned back into a doll\r\nPlease help me make it move again!#k#l \r\n#L1##bTell me more about Pets.#k#l \r\n#L2##bHow do I raise Pets?#k#l \r\n#L3##bDo Pets die too?#k#l \r\n#L4##bWhat are the commands for brown and black kitty?#k#l \r\n#L5##bWhat are the commands for brown puppy?#k#l \r\n#L6##bWhat are the commands for pink and white bunny?#k#l \r\n#L7##bWhat are the commands for Mini Cargo?#k#l \r\n#L8##bWhat are the commands for Husky?#k#l \r\n#L9##bWhat are the commands for Black Pig?#k#l \r\n#L10##bWhat are the commands for Panda#k#l \r\n#L11##bWhat are the commands for Dino Boy & Girl?#k#l \r\n#L12##bWhat are the commands for Rudolph?#k#l \r\n#L13##bWhat are the commands for Monkey?#k#l \r\n#L14##bWhat are the commands for Robot?#k#l \r\n#L15##bWhat are the commands for Elephant?#k#l \r\n#L16##bWhat are the commands for Golden Pig?#k#l \r\n#L17##bWhat are the commands for Penguin?#k#l \r\n#L18##bWhat are the commands for Mini Yeti?#k#l \r\n#L19##bWhat are the commands for Jr. Balrog? \r\n#L20##bWhat are the commands for Baby Dragon?#k#l \r\n#L21##bWhat are the commands for Green/Red/Blue Dragon?#k#l \r\n#L22##bWhat are the commands for Black Dragon?#k#l \r\n#L23##bWhat are the commands for Snowman?#k#l \r\n#L24##bWhat are the commands for Sun Wu Kong?#k#l \r\n#L25##bWhat are the commands for Jr. Reaper?#k#l \r\n#L26##bWhat are the commands for Crystal Rudolph?#k#l \r\n#L27##bWhat are the commands for Kino?#k#l \r\n#L28##bWhat are the commands for White Duck?#k#l \r\n#L29##bWhat are the commands for Pink Bean?#k#l \r\n#L30##bWhat are the commands for Porcupine?#k#l"); else
} status--;
else if(status == 1){
if(selection == 0){ if(status == 0){
cm.sendNext("I'm Wisp, continuing on with the studies that my Master Mar the Fairy assigned me. There seems to be a lot of pets even her in Ludibrium. I need to get back to my studies, so if you'll excuse me..."); cm.sendSimple("Hello there, I'm #bMar the Fairy#k of Victoria Island's main disciple. Mar the Fairy summoned me here to see if the pets are being taken care of here in Ludibrium. What can I do for you? \r\n#L0##bMy pet has turned back into a doll\r\nPlease help me make it move again!#k#l \r\n#L1##bTell me more about Pets.#k#l \r\n#L2##bHow do I raise Pets?#k#l \r\n#L3##bDo Pets die too?#k#l \r\n#L4##bWhat are the commands for brown and black kitty?#k#l \r\n#L5##bWhat are the commands for brown puppy?#k#l \r\n#L6##bWhat are the commands for pink and white bunny?#k#l \r\n#L7##bWhat are the commands for Mini Cargo?#k#l \r\n#L8##bWhat are the commands for Husky?#k#l \r\n#L9##bWhat are the commands for Black Pig?#k#l \r\n#L10##bWhat are the commands for Panda#k#l \r\n#L11##bWhat are the commands for Dino Boy & Girl?#k#l \r\n#L12##bWhat are the commands for Rudolph?#k#l \r\n#L13##bWhat are the commands for Monkey?#k#l \r\n#L14##bWhat are the commands for Robot?#k#l \r\n#L15##bWhat are the commands for Elephant?#k#l \r\n#L16##bWhat are the commands for Golden Pig?#k#l \r\n#L17##bWhat are the commands for Penguin?#k#l \r\n#L18##bWhat are the commands for Mini Yeti?#k#l \r\n#L19##bWhat are the commands for Jr. Balrog? \r\n#L20##bWhat are the commands for Baby Dragon?#k#l \r\n#L21##bWhat are the commands for Green/Red/Blue Dragon?#k#l \r\n#L22##bWhat are the commands for Black Dragon?#k#l \r\n#L23##bWhat are the commands for Snowman?#k#l \r\n#L24##bWhat are the commands for Sun Wu Kong?#k#l \r\n#L25##bWhat are the commands for Jr. Reaper?#k#l \r\n#L26##bWhat are the commands for Crystal Rudolph?#k#l \r\n#L27##bWhat are the commands for Kino?#k#l \r\n#L28##bWhat are the commands for White Duck?#k#l \r\n#L29##bWhat are the commands for Pink Bean?#k#l \r\n#L30##bWhat are the commands for Porcupine?#k#l");
cm.dispose(); }
} else if(selection == 1){ else if(status == 1){
cm.sendNext("Hmmmm,you must have a lot of questions regarding the pets. Long ago, a person by the name #bCloy#k, sprayed Water of Life on it, and cast spell on it to create a magical animal. I know it sounds unbelievable, but it's a doll that became an actual living thing. They understand and follow people very well."); if(selection == 0){
} else if(selection == 2){ cm.sendNext("I'm Wisp, continuing on with the studies that my Master Mar the Fairy assigned me. There seems to be a lot of pets even her in Ludibrium. I need to get back to my studies, so if you'll excuse me...");
cm.sendNext("Depending on the command you give, pets can love it, hate, and display other kinds of reactions to it. If you give the pet a command and it follows you well, your closeness goes up. Double click on the pet and you can check the closeness, level, fullness and etc..."); cm.dispose();
} else if(selection == 3){ } else if(selection == 1){
cm.sendNext("Dying... well, they aren't technically ALIVE per se, so I don't know if dying is the right term to use. They are dolls with my magical power and the power of Water of Life to become a live object. Of course while it's alive, it's just like a live animal..."); cm.sendNext("Hmmmm,you must have a lot of questions regarding the pets. Long ago, a person by the name #bCloy#k, sprayed Water of Life on it, and cast spell on it to create a magical animal. I know it sounds unbelievable, but it's a doll that became an actual living thing. They understand and follow people very well.");
} else if(selection == 4){ } else if(selection == 2){
cm.sendNext("These are the commands for #rBrown Kitty and Black Kitty#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, dummy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpoop#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 10 ~ 30)\r\n#bcutie#k (level 10 ~ 30)\r\n#bup, stand, rise#k (level 20 ~ 30)"); cm.sendNext("Depending on the command you give, pets can love it, hate, and display other kinds of reactions to it. If you give the pet a command and it follows you well, your closeness goes up. Double click on the pet and you can check the closeness, level, fullness and etc...");
cm.dispose(); } else if(selection == 3){
} else if(selection == 5){ cm.sendNext("Dying... well, they aren't technically ALIVE per se, so I don't know if dying is the right term to use. They are dolls with my magical power and the power of Water of Life to become a live object. Of course while it's alive, it's just like a live animal...");
cm.sendNext("These are the commands for #rBrown Puppy#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, baddog, dummy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpee#k (level 10 ~ 30)\r\n#btalk, say, chat, bark#k (level 10 ~ 30)\r\n#bdown#k (level 10 ~ 30)\r\n#bup, stand, rise#k (level 20 ~ 30)"); } else if(selection == 4){
cm.dispose(); cm.sendNext("These are the commands for #rBrown Kitty and Black Kitty#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, dummy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpoop#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 10 ~ 30)\r\n#bcutie#k (level 10 ~ 30)\r\n#bup, stand, rise#k (level 20 ~ 30)");
} else if(selection == 6){ cm.dispose();
cm.sendNext("These are the commands for #rPink Bunny and White Bunny#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bup, stand#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpoop#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 10 ~ 30)\r\n#bhug#k (level 10 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 20 ~ 30)"); } else if(selection == 5){
cm.dispose(); cm.sendNext("These are the commands for #rBrown Puppy#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, baddog, dummy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpee#k (level 10 ~ 30)\r\n#btalk, say, chat, bark#k (level 10 ~ 30)\r\n#bdown#k (level 10 ~ 30)\r\n#bup, stand, rise#k (level 20 ~ 30)");
} else if(selection == 7){ cm.dispose();
cm.sendNext("These are the commands for #rMini Cargo#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bup, stand#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpee#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 10 ~ 30)\r\n#bthelook, charisma#k (level 10 ~ 30)\r\n#bgoodboy, good#k (level 20 ~ 30)"); } else if(selection == 6){
cm.dispose(); cm.sendNext("These are the commands for #rPink Bunny and White Bunny#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bup, stand#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpoop#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 10 ~ 30)\r\n#bhug#k (level 10 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 20 ~ 30)");
} else if(selection == 8){ cm.dispose();
cm.sendNext("These are the commands for #rHusky#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, baddog, dummy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1 ~ 30)\r\n#bpee#k (level 1 ~ 30)\r\n#btalk, say, chat, bark#k (level 10 ~ 30)\r\n#bdown#k (level 10 ~ 30)\r\n#bup, stand, rise#k (level 20 ~ 30)"); } else if(selection == 7){
cm.dispose(); cm.sendNext("These are the commands for #rMini Cargo#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bup, stand#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpee#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 10 ~ 30)\r\n#bthelook, charisma#k (level 10 ~ 30)\r\n#bgoodboy, good#k (level 20 ~ 30)");
} else if(selection == 9){ cm.dispose();
cm.sendNext("These are the commands for #rBlack Pig#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bhand, up, stand#k (level 1 ~ 30)\r\n#btalk, say, chat, hug#k (level 10 ~ 30)\r\n#bsmile#k (level 10 ~ 30)\r\n#blaugh, smile#k (level 10 ~ 30)\r\n#bcharisma, sleep, sleepy, gotobed#k(level 20~30)"); } else if(selection == 8){
cm.dispose(); cm.sendNext("These are the commands for #rHusky#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, baddog, dummy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1 ~ 30)\r\n#bpee#k (level 1 ~ 30)\r\n#btalk, say, chat, bark#k (level 10 ~ 30)\r\n#bdown#k (level 10 ~ 30)\r\n#bup, stand, rise#k (level 20 ~ 30)");
} else if(selection == 10){ cm.dispose();
cm.sendNext("These are the commands for #rPanda#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1 ~ 30)\r\n#bpee#k(level 1 ~ 30)\r\n#bup, stand, hug#k (level 1 ~ 30)\r\n#btalk, chat#k (level 10 ~ 30)\r\n#bplay#k (level 20 ~ 30)\r\n#bmeh, bleh#k (level 10 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 20 ~ 30)"); } else if(selection == 9){
cm.dispose(); cm.sendNext("These are the commands for #rBlack Pig#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#biloveyou#k (level 1~30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bhand, up, stand#k (level 1 ~ 30)\r\n#btalk, say, chat, hug#k (level 10 ~ 30)\r\n#bsmile#k (level 10 ~ 30)\r\n#blaugh, smile#k (level 10 ~ 30)\r\n#bcharisma, sleep, sleepy, gotobed#k(level 20~30)");
} else if(selection == 11){ cm.dispose();
cm.sendNext("These are the commands for #rDino Boy and Dino Girl#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no,, stupid, ihateyou, badboy, badgirl#k (evel 1 ~ 30)\r\n#biloveyou, dummy#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#btalk, chat(level 10 ~ 30)\r\n#bsmile, laugh#k (level 1 ~ 30)\r\n#bcutie#k (level 10 ~ 30)\r\n#bsleep, nap, sleepy#k (level 20 ~ 30)"); } else if(selection == 10){
cm.dispose(); cm.sendNext("These are the commands for #rPanda#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#biloveyou#k (level 1 ~ 30)\r\n#bpee#k(level 1 ~ 30)\r\n#bup, stand, hug#k (level 1 ~ 30)\r\n#btalk, chat#k (level 10 ~ 30)\r\n#bplay#k (level 20 ~ 30)\r\n#bmeh, bleh#k (level 10 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 20 ~ 30)");
} else if(selection == 12){ cm.dispose();
cm.sendNext("These are the commands for #rRudolph#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~30) \r\n#bbad, no, badgirl, badboy#k(level 1~30)\r\n#bup, stand#k(level 1 ~ 30) \r\n#bstupid, ihateyou, dummy#k(level 1 ~ 30) \r\n#bmerryxmas, merrychristmas#k(level 11 ~ 30)\r\n#biloveyou#k(level 1 ~ 30)\r\n#bpoop#k(level 1 ~ 30)\r\n#btalk, say, chat#k(level 11 ~ 30)\r\n#blonely, alone, down, rednose#k(level 11~30),\r\n#bcutie#k(level 11 ~ 30)\r\n#bmush, go#k(level 21 ~ 30)"); } else if(selection == 11){
cm.dispose(); cm.sendNext("These are the commands for #rDino Boy and Dino Girl#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no,, stupid, ihateyou, badboy, badgirl#k (evel 1 ~ 30)\r\n#biloveyou, dummy#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#btalk, chat(level 10 ~ 30)\r\n#bsmile, laugh#k (level 1 ~ 30)\r\n#bcutie#k (level 10 ~ 30)\r\n#bsleep, nap, sleepy#k (level 20 ~ 30)");
} else if (selection == 13) { cm.dispose();
cm.sendNext("These are the commands for #rMonkey#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit, rest#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bup, stand#k(level 1 ~ 30)\r\n#biloveyou, pee#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 11 ~ 30)\r\n#bplay, melong#k (level 11 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 21 ~ 30)"); } else if(selection == 12){
cm.dispose(); cm.sendNext("These are the commands for #rRudolph#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~30) \r\n#bbad, no, badgirl, badboy#k(level 1~30)\r\n#bup, stand#k(level 1 ~ 30) \r\n#bstupid, ihateyou, dummy#k(level 1 ~ 30) \r\n#bmerryxmas, merrychristmas#k(level 11 ~ 30)\r\n#biloveyou#k(level 1 ~ 30)\r\n#bpoop#k(level 1 ~ 30)\r\n#btalk, say, chat#k(level 11 ~ 30)\r\n#blonely, alone, down, rednose#k(level 11~30),\r\n#bcutie#k(level 11 ~ 30)\r\n#bmush, go#k(level 21 ~ 30)");
} else if (selection == 14) { cm.dispose();
cm.sendNext("These are the commands for #rRobot#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit, stand, rise#k (level 1 ~ 30)\r\n#battack, bad, no, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, dummy#k (level 1 ~ 30)\r\n#biloveyou, good#k (level 1 ~ 30)\r\n#bspeak, disguise#k (level 11 ~ 30)"); } else if (selection == 13) {
cm.dispose(); cm.sendNext("These are the commands for #rMonkey#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit, rest#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bup, stand#k(level 1 ~ 30)\r\n#biloveyou, pee#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 11 ~ 30)\r\n#bplay, melong#k (level 11 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 21 ~ 30)");
} else if (selection == 15) { cm.dispose();
cm.sendNext("These are the commands for #rElephant#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit, rest#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bup, stand, rise#k(level 1 ~ 30)\r\n#biloveyou, pee#k (level 1 ~ 30)\r\n#btalk, say, chat, play#k (level 11 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 21 ~ 30)"); } else if (selection == 14) {
cm.dispose(); cm.sendNext("These are the commands for #rRobot#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit, stand, rise#k (level 1 ~ 30)\r\n#battack, bad, no, badboy#k (level 1 ~ 30)\r\n#bstupid, ihateyou, dummy#k (level 1 ~ 30)\r\n#biloveyou, good#k (level 1 ~ 30)\r\n#bspeak, disguise#k (level 11 ~ 30)");
} else if (selection == 16) { cm.dispose();
cm.sendNext("These are the commands for #rGolden Pig#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bpoop, iloveyou#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 11 ~ 30)\r\n#bloveme, hugme#k (level 11 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 21 ~ 30)\r\n#bimpressed, outofhere#k (level 21 ~ 30)\r\n#broll, showmethemoney#k (level 21 ~ 30)"); } else if (selection == 15) {
cm.dispose(); cm.sendNext("These are the commands for #rElephant#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit, rest#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bup, stand, rise#k(level 1 ~ 30)\r\n#biloveyou, pee#k (level 1 ~ 30)\r\n#btalk, say, chat, play#k (level 11 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 21 ~ 30)");
} else if (selection == 17) { cm.dispose();
cm.sendNext("These are the commands for #rPenguin#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bup, stand, rise#k (level 1 ~ 30)\r\n#biloveyou#k (level 1 ~ 30)\r\n#btalk, chat, say#k (level 10 ~ 30)\r\n#bhug, hugme#k (level 10 ~ 30)\r\n#bwing, hand#k (level 10 ~ 30)\r\n#bsleep#k (level 20 ~ 30)\r\n#bkiss, smooch, muah#k (level 20 ~ 30)\r\n#bfly#k (level 20 ~ 30)\r\n#bcute, adorable#k (level 20 ~ 30)"); } else if (selection == 16) {
cm.dispose(); cm.sendNext("These are the commands for #rGolden Pig#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bpoop, iloveyou#k (level 1 ~ 30)\r\n#btalk, say, chat#k (level 11 ~ 30)\r\n#bloveme, hugme#k (level 11 ~ 30)\r\n#bsleep, sleepy, gotobed#k (level 21 ~ 30)\r\n#bimpressed, outofhere#k (level 21 ~ 30)\r\n#broll, showmethemoney#k (level 21 ~ 30)");
} else if (selection == 18) { cm.dispose();
cm.sendNext("These are the commands for #rMini Yeti#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bdance, boogie, shakeit#k (level 1 ~ 30)\r\n#bcute, cutie, pretty, adorable#k (level 1 ~ 30)\r\n#biloveyou, likeyou, mylove#k (level 1 ~ 30)\r\n#btalk, chat, say#k (level 10 ~ 30)\r\n#bsleep, nap#k (level 10 ~ 30)"); } else if (selection == 17) {
cm.dispose(); cm.sendNext("These are the commands for #rPenguin#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bup, stand, rise#k (level 1 ~ 30)\r\n#biloveyou#k (level 1 ~ 30)\r\n#btalk, chat, say#k (level 10 ~ 30)\r\n#bhug, hugme#k (level 10 ~ 30)\r\n#bwing, hand#k (level 10 ~ 30)\r\n#bsleep#k (level 20 ~ 30)\r\n#bkiss, smooch, muah#k (level 20 ~ 30)\r\n#bfly#k (level 20 ~ 30)\r\n#bcute, adorable#k (level 20 ~ 30)");
} else if (selection == 19) { cm.dispose();
cm.sendNext("These are the commands for #rJr. Balrog#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bliedown#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#biloveyou|mylove|likeyou#k (level 1 ~ 30)\r\n#bcute|cutie|pretty|adorable#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bsmirk|crooked|laugh#k (level 1 ~ 30)\r\n#bmelong#k (level 11 ~ 30)\r\n#bgood|thelook|charisma#k (level 11 ~ 30)\r\n#bspeak|talk|chat|say#k (level 11 ~ 30)\r\n#bsleep|nap|sleepy#k (level 11 ~ 30)\r\n#bgas#k (level 21 ~ 30)"); } else if (selection == 18) {
cm.dispose(); cm.sendNext("These are the commands for #rMini Yeti#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad, no, badboy, badgirl#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bdance, boogie, shakeit#k (level 1 ~ 30)\r\n#bcute, cutie, pretty, adorable#k (level 1 ~ 30)\r\n#biloveyou, likeyou, mylove#k (level 1 ~ 30)\r\n#btalk, chat, say#k (level 10 ~ 30)\r\n#bsleep, nap#k (level 10 ~ 30)");
} else if (selection == 20) { cm.dispose();
cm.sendNext("These are the commands for #rBaby Dragon#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#biloveyou|loveyou#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bstupid|ihateyou|dummy#k (level 1 ~ 30)\r\n#bcutie#k (level 11 ~ 30)\r\n#btalk|chat|say#k (level 11 ~ 30)\r\n#bsleep|sleepy|gotobed#k (level 11 ~ 30)"); } else if (selection == 19) {
cm.dispose(); cm.sendNext("These are the commands for #rJr. Balrog#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bliedown#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#biloveyou|mylove|likeyou#k (level 1 ~ 30)\r\n#bcute|cutie|pretty|adorable#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bsmirk|crooked|laugh#k (level 1 ~ 30)\r\n#bmelong#k (level 11 ~ 30)\r\n#bgood|thelook|charisma#k (level 11 ~ 30)\r\n#bspeak|talk|chat|say#k (level 11 ~ 30)\r\n#bsleep|nap|sleepy#k (level 11 ~ 30)\r\n#bgas#k (level 21 ~ 30)");
} else if (selection == 21) { cm.dispose();
cm.sendNext("These are the commands for #rGreen/Red/Blue Dragon#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 15 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 15 ~ 30)\r\n#biloveyou|loveyou#k (level 15 ~ 30)\r\n#bpoop#k (level 15 ~ 30)\r\n#bstupid|ihateyou|dummy#k (level 15 ~ 30)\r\n#btalk|chat|say#k (level 15 ~ 30)\r\n#bsleep|sleepy|gotobed#k (level 15 ~ 30)\r\n#bchange#k (level 21 ~ 30)"); } else if (selection == 20) {
cm.dispose(); cm.sendNext("These are the commands for #rBaby Dragon#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#biloveyou|loveyou#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bstupid|ihateyou|dummy#k (level 1 ~ 30)\r\n#bcutie#k (level 11 ~ 30)\r\n#btalk|chat|say#k (level 11 ~ 30)\r\n#bsleep|sleepy|gotobed#k (level 11 ~ 30)");
} else if (selection == 22) { cm.dispose();
cm.sendNext("These are the commands for #rBlack Dragon#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 15 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 15 ~ 30)\r\n#biloveyou|loveyou#k (level 15 ~ 30)\r\n#bpoop#k (level 15 ~ 30)\r\n#bstupid|ihateyou|dummy#k (level 15 ~ 30)\r\n#btalk|chat|say#k (level 15 ~ 30)\r\n#bsleep|sleepy|gotobed#k (level 15 ~ 30)\r\n#bcutie, change#k (level 21 ~ 30)"); } else if (selection == 21) {
cm.dispose(); cm.sendNext("These are the commands for #rGreen/Red/Blue Dragon#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 15 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 15 ~ 30)\r\n#biloveyou|loveyou#k (level 15 ~ 30)\r\n#bpoop#k (level 15 ~ 30)\r\n#bstupid|ihateyou|dummy#k (level 15 ~ 30)\r\n#btalk|chat|say#k (level 15 ~ 30)\r\n#bsleep|sleepy|gotobed#k (level 15 ~ 30)\r\n#bchange#k (level 21 ~ 30)");
} else if (selection == 23) { cm.dispose();
cm.sendNext("These are the commands for #rSnowman#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bstupid, ihateyou, dummy#k (level 1 ~ 30)\r\n#bloveyou, mylove, ilikeyou#k (level 1 ~ 30)\r\n#bmerrychristmas#k (level 1 ~ 30)\r\n#bcutie, adorable, cute, pretty#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#btalk, chat, say/sleep, sleepy, gotobed#k (level 10 ~ 30)\r\n#bchang#k (level 20 ~ 30)"); } else if (selection == 22) {
cm.dispose(); cm.sendNext("These are the commands for #rBlack Dragon#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 15 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 15 ~ 30)\r\n#biloveyou|loveyou#k (level 15 ~ 30)\r\n#bpoop#k (level 15 ~ 30)\r\n#bstupid|ihateyou|dummy#k (level 15 ~ 30)\r\n#btalk|chat|say#k (level 15 ~ 30)\r\n#bsleep|sleepy|gotobed#k (level 15 ~ 30)\r\n#bcutie, change#k (level 21 ~ 30)");
} else if (selection == 24) { cm.dispose();
cm.sendNext("These are the commands for #rSun Wu Kong#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~ 30)\r\n#bno,bad,badgirl,badboy#k(level 1 ~ 30) \r\n#bpoope#k(level 1 ~ 30) \r\n#bcutie,adorable,cute,pretty#k(level 1 ~ 30) \r\n#biloveyou,loveyou,luvyou,ilikeyou,mylove#k(level 1 ~ 30) \r\n#btalk,chat,say/sleep,sleepy,gotobed#k(level 10 ~ 30) \r\n#btransform#k(level 20 ~ 30)"); } else if (selection == 23) {
cm.dispose(); cm.sendNext("These are the commands for #rSnowman#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bstupid, ihateyou, dummy#k (level 1 ~ 30)\r\n#bloveyou, mylove, ilikeyou#k (level 1 ~ 30)\r\n#bmerrychristmas#k (level 1 ~ 30)\r\n#bcutie, adorable, cute, pretty#k (level 1 ~ 30)\r\n#bbad, no, badgirl, badboy#k (level 1 ~ 30)\r\n#btalk, chat, say/sleep, sleepy, gotobed#k (level 10 ~ 30)\r\n#bchang#k (level 20 ~ 30)");
} else if (selection == 25) { cm.dispose();
cm.sendNext("These are the commands for #rJr. Reaper#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#bplaydead, poop#k (level 1 ~ 30)\r\n#btalk|chat|say#k (level 1 ~ 30)\r\n#biloveyou, hug#k (level 1 ~ 30)\r\n#bsmellmyfeet, rockout, boo#k (level 1 ~ 30)\r\n#btrickortreat#k (level 1 ~ 30)\r\n#bmonstermash#k (level 1 ~ 30)"); } else if (selection == 24) {
cm.dispose(); cm.sendNext("These are the commands for #rSun Wu Kong#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~ 30)\r\n#bno,bad,badgirl,badboy#k(level 1 ~ 30) \r\n#bpoope#k(level 1 ~ 30) \r\n#bcutie,adorable,cute,pretty#k(level 1 ~ 30) \r\n#biloveyou,loveyou,luvyou,ilikeyou,mylove#k(level 1 ~ 30) \r\n#btalk,chat,say/sleep,sleepy,gotobed#k(level 10 ~ 30) \r\n#btransform#k(level 20 ~ 30)");
} else if (selection == 26) { cm.dispose();
cm.sendNext("These are the commands for #rCrystal Rudolph#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|badgirl|badboy#k (level 1 ~ 30)\r\n#bbleh|joke#k(level 1~30)\r\n#bdisguise|transform#k(level 1 ~ 30) \r\n#bawesome|feelgood|lalala#k(level 1 ~ 30) \r\n#bloveyou|heybabe#k(level 1 ~ 30) \r\n#btalk|say|chat#k(level 10 ~ 30) \r\n#bsleep|sleepy|nap|gotobed#k(level 20 ~ 30)"); } else if (selection == 25) {
cm.dispose(); cm.sendNext("These are the commands for #rJr. Reaper#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#bplaydead, poop#k (level 1 ~ 30)\r\n#btalk|chat|say#k (level 1 ~ 30)\r\n#biloveyou, hug#k (level 1 ~ 30)\r\n#bsmellmyfeet, rockout, boo#k (level 1 ~ 30)\r\n#btrickortreat#k (level 1 ~ 30)\r\n#bmonstermash#k (level 1 ~ 30)");
} else if (selection == 27) { cm.dispose();
cm.sendNext("These are the commands for #rKino#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad|no|badgirl|badboy#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bsleep|nap|sleepy|gotobed#k(level 1 ~ 30) \r\n#btalk|say|chat#k(level 10 ~ 30) \r\n#biloveyou|mylove|likeyou#k(level 10 ~ 30) \r\n#bmeh|bleh#k(level 10 ~ 30) \r\n#bdisguise|change|transform#k(level 20 ~ 30)"); } else if (selection == 26) {
cm.dispose(); cm.sendNext("These are the commands for #rCrystal Rudolph#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|badgirl|badboy#k (level 1 ~ 30)\r\n#bbleh|joke#k(level 1~30)\r\n#bdisguise|transform#k(level 1 ~ 30) \r\n#bawesome|feelgood|lalala#k(level 1 ~ 30) \r\n#bloveyou|heybabe#k(level 1 ~ 30) \r\n#btalk|say|chat#k(level 10 ~ 30) \r\n#bsleep|sleepy|nap|gotobed#k(level 20 ~ 30)");
} else if (selection == 28) { cm.dispose();
cm.sendNext("These are the commands for #rWhite Duck#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~ 30) \r\n#bbad|no|badgirl|badboy#k(level 1 ~ 30) \r\n#bup|stand#k(level 1 ~ 30) \r\n#bpoop#k(level 1 ~ 30) \r\n#btalk|chat|say#k(level 1 ~ 30) \r\n#bhug#k(level 1 ~ 30) \r\n#bloveyou#k(level 1 ~ 30) \r\n#bcutie#k(level 1 ~ 30) \r\n#bsleep#k(level 1 ~ 30) \r\n#bsmarty(level 10 ~ 30) \r\n#bdance#k (level 20 ~ 30) \r\n#bswan#k(level 20 ~ 30)"); } else if (selection == 27) {
cm.dispose(); cm.sendNext("These are the commands for #rKino#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bbad|no|badgirl|badboy#k (level 1 ~ 30)\r\n#bpoop#k (level 1 ~ 30)\r\n#bsleep|nap|sleepy|gotobed#k(level 1 ~ 30) \r\n#btalk|say|chat#k(level 10 ~ 30) \r\n#biloveyou|mylove|likeyou#k(level 10 ~ 30) \r\n#bmeh|bleh#k(level 10 ~ 30) \r\n#bdisguise|change|transform#k(level 20 ~ 30)");
} else if (selection == 29){ cm.dispose();
cm.sendNext("These are the commands for #rPink Bean#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~ 30) \r\n#bbad|no|badgirl|badboy|poop#k(level 1 ~ 30) \r\n#blazy|dummy|ihateyoutalk|chat|say|mumbleiloveyou|hugme|loveyou|#k(level 1 ~ 30) \r\n#bshake|music|charmbleh|joke|boo#k(level 20 ~ 30) \r\n#bgotobed|sleep|sleepypoke|stinky|dummy|ihateyou#k(level 20 ~ 30)\r\n#bkongkong#k(level 30)"); } else if (selection == 28) {
cm.dispose(); cm.sendNext("These are the commands for #rWhite Duck#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~ 30) \r\n#bbad|no|badgirl|badboy#k(level 1 ~ 30) \r\n#bup|stand#k(level 1 ~ 30) \r\n#bpoop#k(level 1 ~ 30) \r\n#btalk|chat|say#k(level 1 ~ 30) \r\n#bhug#k(level 1 ~ 30) \r\n#bloveyou#k(level 1 ~ 30) \r\n#bcutie#k(level 1 ~ 30) \r\n#bsleep#k(level 1 ~ 30) \r\n#bsmarty(level 10 ~ 30) \r\n#bdance#k (level 20 ~ 30) \r\n#bswan#k(level 20 ~ 30)");
} else if (selection == 30){ cm.dispose();
cm.sendNext("These are the commands for #rPorcupine#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#bhugcushion|sleep|knit|poop#k (level 1 ~ 30)\r\n#bcomb|beach#k (level 10 ~ 30)\r\n#btreeninja|dart#k (level 20 ~ 30)"); } else if (selection == 29){
cm.dispose(); cm.sendNext("These are the commands for #rPink Bean#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k(level 1 ~ 30) \r\n#bbad|no|badgirl|badboy|poop#k(level 1 ~ 30) \r\n#blazy|dummy|ihateyoutalk|chat|say|mumbleiloveyou|hugme|loveyou|#k(level 1 ~ 30) \r\n#bshake|music|charmbleh|joke|boo#k(level 20 ~ 30) \r\n#bgotobed|sleep|sleepypoke|stinky|dummy|ihateyou#k(level 20 ~ 30)\r\n#bkongkong#k(level 30)");
} cm.dispose();
} else if(status == 2){ } else if (selection == 30){
cm.sendNextPrev("But Water of Life only comes out little at the very bottom of the World Tree, so those babies can't be alive forever... I know, it's very unfortunate... but even if it becomes a doll again they can be brought back to life so be good to it while you're with it."); cm.sendNext("These are the commands for #rPorcupine#k. The level mentioned next to the command shows the pet level required for it to respond.\r\n#bsit#k (level 1 ~ 30)\r\n#bno|bad|badgirl|badboy#k (level 1 ~ 30)\r\n#bhugcushion|sleep|knit|poop#k (level 1 ~ 30)\r\n#bcomb|beach#k (level 10 ~ 30)\r\n#btreeninja|dart#k (level 20 ~ 30)");
} else if(status == 3){ cm.dispose();
cm.sendNextPrev("Oh yeah, they'll react when you give them special commands. You can scold them, love them.. it all depends on how you take care of them. They are afraid to leave their masters so be nice to them, show them love. They can get sad and lonely fast.."); }
cm.dispose(); } else if(status == 2){
} else if(status == 4){ cm.sendNextPrev("But Water of Life only comes out little at the very bottom of the World Tree, so those babies can't be alive forever... I know, it's very unfortunate... but even if it becomes a doll again they can be brought back to life so be good to it while you're with it.");
cm.sendNextPrev("Talk to the pet, pay attention to it and its closeness level will go up and eventually his overall level will go up too. As the closeness rises, the pet's overall level will rise soon after. As the overall level rises, one day the pet may even talk like a person a little bit, so try hard raising it. Of course it won't be easy doing so..."); } else if(status == 3){
} else if(status == 5){ cm.sendNextPrev("Oh yeah, they'll react when you give them special commands. You can scold them, love them.. it all depends on how you take care of them. They are afraid to leave their masters so be nice to them, show them love. They can get sad and lonely fast..");
cm.sendNextPrev("It may be a live doll but they also have life so they can feel the hunger too. #bFullness#k shows the level of hunger the pet's in. 100 is the max, and the lower it gets, it means that the pet is getting hungrier. After a while, it won't even follow your command and be on the offensive, so watch out over that."); cm.dispose();
} else if(status == 6){ } else if(status == 4){
cm.sendNextPrev("That's right! Pets can't eat the normal human food. Instead a teddy bear in Ludibrium called #bPatricia#k sells #bPet Food#k so if you need food for your pet, find #bPatricia#k It'll be a good idea to buy the food in advance and feed the pet before it gets really hungry."); cm.sendNextPrev("Talk to the pet, pay attention to it and its closeness level will go up and eventually his overall level will go up too. As the closeness rises, the pet's overall level will rise soon after. As the overall level rises, one day the pet may even talk like a person a little bit, so try hard raising it. Of course it won't be easy doing so...");
} else if(status == 7){ } else if(status == 5){
cm.sendNextPrev("Oh, and if you don't feed the pet for a long period of time, it goes back home by itself. You can take it out of its home and feed it but it's not really good for the pet's health, so try feeding him on a regular basis so it doesn't go down to that level, alright? I think this will do."); cm.sendNextPrev("It may be a live doll but they also have life so they can feel the hunger too. #bFullness#k shows the level of hunger the pet's in. 100 is the max, and the lower it gets, it means that the pet is getting hungrier. After a while, it won't even follow your command and be on the offensive, so watch out over that.");
cm.dispose(); } else if(status == 6){
} else if(status == 8){ cm.sendNextPrev("That's right! Pets can't eat the normal human food. Instead a teddy bear in Ludibrium called #bPatricia#k sells #bPet Food#k so if you need food for your pet, find #bPatricia#k It'll be a good idea to buy the food in advance and feed the pet before it gets really hungry.");
cm.sendNextPrev("After some time... that's correct, they stop moving. They just turn back to being a doll, after the effect of magic dies down and Water of Life dries out. But that doesn't mean it's stopped forever, because once you pour Water of Life over, it's going to be back alive."); } else if(status == 7){
} else if(status == 9){ cm.sendNextPrev("Oh, and if you don't feed the pet for a long period of time, it goes back home by itself. You can take it out of its home and feed it but it's not really good for the pet's health, so try feeding him on a regular basis so it doesn't go down to that level, alright? I think this will do.");
cm.sendNextPrev("Even if it someday moves again, it's sad to see them stop altogether. Please be nice to them while they are alive and moving. Feed them well, too. Isn't it nice to know that there's something alive that follows and listens to only you?"); cm.dispose();
cm.dispose(); } else if(status == 8){
} cm.sendNextPrev("After some time... that's correct, they stop moving. They just turn back to being a doll, after the effect of magic dies down and Water of Life dries out. But that doesn't mean it's stopped forever, because once you pour Water of Life over, it's going to be back alive.");
} } else if(status == 9){
cm.sendNextPrev("Even if it someday moves again, it's sad to see them stop altogether. Please be nice to them while they are alive and moving. Feed them well, too. Isn't it nice to know that there's something alive that follows and listens to only you?");
cm.dispose();
}
}
} }
+1 -1
View File
@@ -19,7 +19,7 @@
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//First version by Moogra //First version thanks to Moogra
/** /**
* @author: Ronan * @author: Ronan
+60
View File
@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Meteorite
@Author RonanLana (Ronan)
*/
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.isQuestStarted(3421)) {
var meteoriteId = cm.getNpc() - 2050014;
var progress = cm.getQuestProgress(3421, 0);
if((progress >> meteoriteId) % 2 == 0 || (progress == 63 && !cm.haveItem(4031117, 6))) {
progress |= (1 << meteoriteId);
cm.gainItem(4031117, 1);
cm.setQuestProgress(3421, 0, progress);
}
}
cm.dispose();
}
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Meteorite
@Author RonanLana (Ronan)
*/
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.isQuestStarted(3421)) {
var meteoriteId = cm.getNpc() - 2050014;
var progress = cm.getQuestProgress(3421, 0);
if((progress >> meteoriteId) % 2 == 0 || (progress == 63 && !cm.haveItem(4031117, 6))) {
progress |= (1 << meteoriteId);
cm.gainItem(4031117, 1);
cm.setQuestProgress(3421, 0, progress);
}
}
cm.dispose();
}
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Meteorite
@Author RonanLana (Ronan)
*/
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.isQuestStarted(3421)) {
var meteoriteId = cm.getNpc() - 2050014;
var progress = cm.getQuestProgress(3421, 0);
if((progress >> meteoriteId) % 2 == 0 || (progress == 63 && !cm.haveItem(4031117, 6))) {
progress |= (1 << meteoriteId);
cm.gainItem(4031117, 1);
cm.setQuestProgress(3421, 0, progress);
}
}
cm.dispose();
}
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Meteorite
@Author RonanLana (Ronan)
*/
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.isQuestStarted(3421)) {
var meteoriteId = cm.getNpc() - 2050014;
var progress = cm.getQuestProgress(3421, 0);
if((progress >> meteoriteId) % 2 == 0 || (progress == 63 && !cm.haveItem(4031117, 6))) {
progress |= (1 << meteoriteId);
cm.gainItem(4031117, 1);
cm.setQuestProgress(3421, 0, progress);
}
}
cm.dispose();
}
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Meteorite
@Author RonanLana (Ronan)
*/
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.isQuestStarted(3421)) {
var meteoriteId = cm.getNpc() - 2050014;
var progress = cm.getQuestProgress(3421, 0);
if((progress >> meteoriteId) % 2 == 0 || (progress == 63 && !cm.haveItem(4031117, 6))) {
progress |= (1 << meteoriteId);
cm.gainItem(4031117, 1);
cm.setQuestProgress(3421, 0, progress);
}
}
cm.dispose();
}
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Meteorite
@Author RonanLana (Ronan)
*/
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.isQuestStarted(3421)) {
var meteoriteId = cm.getNpc() - 2050014;
var progress = cm.getQuestProgress(3421, 0);
if((progress >> meteoriteId) % 2 == 0 || (progress == 63 && !cm.haveItem(4031117, 6))) {
progress |= (1 << meteoriteId);
cm.gainItem(4031117, 1);
cm.setQuestProgress(3421, 0, progress);
}
}
cm.dispose();
}
}
}
+1 -1
View File
@@ -19,7 +19,7 @@
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//Fixed by Moogra, Ronan //@Author Moogra, Ronan
//Fixed grammar, javascript syntax //Fixed grammar, javascript syntax
importPackage(Packages.client); importPackage(Packages.client);
+1 -1
View File
@@ -96,7 +96,7 @@ function action(mode, type, selection) {
} }
} else { } else {
if(!cm.isEventLeader()) { if(!cm.isEventLeader()) {
cm.sendOk("Only your event leader is allowed to interact with the Schedule."); cm.sendOk("Only your party leader is allowed to interact with the Schedule.");
} else if(cm.getMapId() == 240050100) { } else if(cm.getMapId() == 240050100) {
if(cm.haveItem(4001087) && cm.haveItem(4001088) && cm.haveItem(4001089) && cm.haveItem(4001090) && cm.haveItem(4001091)) { if(cm.haveItem(4001087) && cm.haveItem(4001088) && cm.haveItem(4001089) && cm.haveItem(4001090) && cm.haveItem(4001091)) {
cm.gainItem(4001087, -1); cm.gainItem(4001087, -1);
+1 -1
View File
@@ -20,7 +20,7 @@
*/ */
/*Mark of the Squad /*Mark of the Squad
* *
*@author SharpAceX (Alan) *@author Alan (SharpAceX)
*@author Ronan *@author Ronan
*/ */
importPackage(Packages.server.expeditions); importPackage(Packages.server.expeditions);
+1 -1
View File
@@ -1,4 +1,4 @@
/* @author aaroncsn(MapleSea Like) /* @author aaroncsn <MapleSea Like>
* @author Ronan * @author Ronan
NPC Name: Mr. Do NPC Name: Mr. Do
Map(s): Mu Lung: Mu Lung(2500000000) Map(s): Mu Lung: Mu Lung(2500000000)
+1 -1
View File
@@ -29,7 +29,7 @@ function action(mode, type, selection) {
var eim = cm.getEventInstance(); var eim = cm.getEventInstance();
if (eim == null) { if (eim == null) {
cm.warp(251010404,0); cm.warp(251010404,0);
cm.sendNext("How are you even here without being registered on an event?"); cm.sendNext("How are you even here without being registered on an instance?");
cm.dispose(); cm.dispose();
return; return;
} }
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn (MapleSea Like) /* Author: aaroncsn <MapleSea Like>
NPC Name: Muhammad NPC Name: Muhammad
Map(s): Ariant:The Town of Ariant(260000200) Map(s): Ariant:The Town of Ariant(260000200)
Description: Jewel Refiner Description: Jewel Refiner
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn (MapleSea Like) /* Author: aaroncsn <MapleSea Like>
NPC Name: Shati NPC Name: Shati
Map(s): The Burning Road: Ariant(2600000000) Map(s): The Burning Road: Ariant(2600000000)
Description: Assistant Hairdresser Description: Assistant Hairdresser
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn (MapleSea Like) /* Author: aaroncsn <MapleSea Like>
NPC Name: Mazra NPC Name: Mazra
Map(s): The Burning Road: Ariant(2600000000) Map(s): The Burning Road: Ariant(2600000000)
Description: Hair Salon Owner Description: Hair Salon Owner
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn (MapleSea Like)(Incomplete- Needs skin id) /* Author: aaroncsn <(MapleSea Like)(Incomplete- Needs skin id)>
NPC Name: Laila NPC Name: Laila
Map(s): The Burning Road: Ariant(2600000000) Map(s): The Burning Road: Ariant(2600000000)
Description: Skin Care Specialist Description: Skin Care Specialist
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn (MapleSea Like) /* Author: aaroncsn <MapleSea Like>
NPC Name: Badr NPC Name: Badr
Map(s): The Burning Road: Ariant(2600000000) Map(s): The Burning Road: Ariant(2600000000)
Description: Ariant Plastic Surgery Description: Ariant Plastic Surgery
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn (MapleSea Like) /* Author: aaroncsn <MapleSea Like>
NPC Name: Aldin NPC Name: Aldin
Map(s): The Burning Road: Ariant(2600000000) Map(s): The Burning Road: Ariant(2600000000)
Description: Ariant Plastic Surgery Description: Ariant Plastic Surgery
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn(MapleSea Like) /* Author: aaroncsn <MapleSea Like>
NPC Name: Karcasa NPC Name: Karcasa
Map(s): The Burning Sands: Tents of the Entertainers(260010600) Map(s): The Burning Sands: Tents of the Entertainers(260010600)
Description: Warps to Victoria Island Description: Warps to Victoria Island
+1 -1
View File
@@ -23,7 +23,7 @@
-- Odin JavaScript -------------------------------------------------------------------------------- -- Odin JavaScript --------------------------------------------------------------------------------
Camel Cab - Magatia (GMS Like) Camel Cab - Magatia (GMS Like)
-- Version Info ----------------------------------------------------------------------------------- -- Version Info -----------------------------------------------------------------------------------
1.3 - Actually fixed by SharpAceX (Alan) 1.3 - Actually fixed by Alan (SharpAceX)
1.2 - Fixed and recoded by Moogra 1.2 - Fixed and recoded by Moogra
1.1 - Shortened by Moogra 1.1 - Shortened by Moogra
1.0 - First Version by Maple4U, who actually can't code at all 1.0 - First Version by Maple4U, who actually can't code at all
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn(MapleSea Like)(Incomplete) /* Author: aaroncsn <(MapleSea Like)(Incomplete)>
NPC Name: Athena Pierce NPC Name: Athena Pierce
Map(s): Altair Camp: Conference Hall(300000010) Map(s): Altair Camp: Conference Hall(300000010)
Description: Unknown Description: Unknown
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn(MapleSea Like)(Incomplete) /* Author: aaroncsn <(MapleSea Like)(Incomplete)>
NPC Name: Euryth NPC Name: Euryth
Map(s): Elin Forest:Altair Camp(300000000) Map(s): Elin Forest:Altair Camp(300000000)
Description: Unknown Description: Unknown
+1 -1
View File
@@ -1,4 +1,4 @@
/* Author: aaroncsn(MapleSea Like)(Incomplete) /* Author: aaroncsn <(MapleSea Like)(Incomplete)>
NPC Name: Kanderun NPC Name: Kanderun
Map(s): Elin Forest:Entrance to Rocky Mountain(300010400) Map(s): Elin Forest:Entrance to Rocky Mountain(300010400)
Description: Unknown Description: Unknown
+1 -1
View File
@@ -43,7 +43,7 @@ function action(mode, type, selection) {
cm.warp(270050000); cm.warp(270050000);
} }
else { else {
cm.sendOk("You cannot receive an event prize without having an empty room in your EQUIP, USE, SET-UP and ETC inventory."); cm.sendOk("You cannot receive an instance prize without having an empty room in your EQUIP, USE, SET-UP and ETC inventory.");
} }
cm.dispose(); cm.dispose();
+3 -3
View File
@@ -89,7 +89,7 @@ function action(mode, type, selection) {
cm.sendOk("Your party completed such an astounding feat coming this far, #byou have defeated all the bosses#k, congratulations! Now I will be handing your reward as you are being transported out..."); cm.sendOk("Your party completed such an astounding feat coming this far, #byou have defeated all the bosses#k, congratulations! Now I will be handing your reward as you are being transported out...");
} }
else { else {
cm.sendOk("For #bdefeating all bosses#k in this event, congratulations! You will now receive a prize that matches your performance here as I warp you out."); cm.sendOk("For #bdefeating all bosses#k in this instance, congratulations! You will now receive a prize that matches your performance here as I warp you out.");
} }
} }
else if(state == 2) { else if(state == 2) {
@@ -109,7 +109,7 @@ function action(mode, type, selection) {
return; return;
} }
} else if(state == 1) { } else if(state == 1) {
cm.sendYesNo("Do you wish to abandon this event?"); cm.sendYesNo("Do you wish to abandon this instance?");
} }
else { else {
em = cm.getEventManager("BossRushPQ"); em = cm.getEventManager("BossRushPQ");
@@ -174,7 +174,7 @@ function action(mode, type, selection) {
cm.sendOk("Try using a Super Megaphone or asking your buddies or guild to join!"); cm.sendOk("Try using a Super Megaphone or asking your buddies or guild to join!");
cm.dispose(); cm.dispose();
} else { } else {
cm.sendOk("#e#b<Party Quest: Boss Rush>#k#n\r\nBrave adventurers from all over the places travels here to test their skills and abilities in combat, as they face even more powerful bosses from MapleStory. Join forces with fellow adventurers or face all the burden by yourself and receive all the glory, it is up to you. REWARDS are given accordingly to how far the adventurers reach and extra prizes may are given to a random member of the party, all attributed at the end of an expedition.\r\n\r\nThis event also supports #bmultiple lobbies for matchmaking several ranges of team levels#k at once: team up with players with lower level if you want better chances to swiftly set up a boss rush for your team."); cm.sendOk("#e#b<Party Quest: Boss Rush>#k#n\r\nBrave adventurers from all over the places travels here to test their skills and abilities in combat, as they face even more powerful bosses from MapleStory. Join forces with fellow adventurers or face all the burden by yourself and receive all the glory, it is up to you. REWARDS are given accordingly to how far the adventurers reach and extra prizes may are given to a random member of the party, all attributed at the end of an expedition.\r\n\r\nThis instance also supports #bmultiple lobbies for matchmaking several ranges of team levels#k at once: team up with players with lower level if you want better chances to swiftly set up a boss rush for your team.");
cm.dispose(); cm.dispose();
} }
} }
+1 -1
View File
@@ -20,7 +20,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** /**
* @Author : iAkira/Kevintjuh93 * @Author : iAkira, Kevintjuh93
**/ **/
var status = 0; var status = 0;
var selected = 0; var selected = 0;
+6 -8
View File
@@ -66,14 +66,13 @@ function action(mode, type, selection) {
} else { } else {
stage = parseInt(eim.getProperty("stage1phase")); stage = parseInt(eim.getProperty("stage1phase"));
} }
if (stage == 1) { if (stage == 1) {
cm.sendOk("In this challenge, I shall show a pattern on the statues around me. When I give the word, repeat the pattern to me to proceed."); cm.sendOk("In this challenge, I shall show a pattern on the statues around me. When I give the word, repeat the pattern to me to proceed.");
} } else {
else {
cm.sendOk("I shall now present a more difficult puzzle for you. Good luck."); cm.sendOk("I shall now present a more difficult puzzle for you. Good luck.");
} }
} } else if (eim.getProperty("stage1status").equals("active")) {
else if (eim.getProperty("stage1status").equals("active")) {
stage = parseInt(eim.getProperty("stage1phase")); stage = parseInt(eim.getProperty("stage1phase"));
if (eim.getProperty("stage1combo").equals(eim.getProperty("stage1guess"))) { if (eim.getProperty("stage1combo").equals(eim.getProperty("stage1guess"))) {
@@ -97,8 +96,7 @@ function action(mode, type, selection) {
} }
eim.setProperty("stage1status", "waiting"); eim.setProperty("stage1status", "waiting");
cm.dispose(); cm.dispose();
} } else {
else {
cm.sendOk("The statues are working on the pattern. Please wait."); cm.sendOk("The statues are working on the pattern. Please wait.");
cm.dispose(); cm.dispose();
} }
@@ -116,7 +114,7 @@ function action(mode, type, selection) {
cm.dispose(); cm.dispose();
} }
} else { } else {
cm.sendOk("I need the leader of this event to speak with me, nobody else."); cm.sendOk("I need the leader of this instance to speak with me, nobody else.");
cm.dispose(); cm.dispose();
} }
} }
@@ -134,7 +132,7 @@ function getReactors() {
reactors.push(mo.getObjectId()); reactors.push(mo.getObjectId());
} }
} }
return reactors; return reactors;
} }
+1 -1
View File
@@ -43,7 +43,7 @@ function start() {
} }
} }
else { else {
cm.sendOk("This is your final challenge. Defeat the evil lurking within the Rubian and let your event leader return it to me. That is all."); cm.sendOk("This is your final challenge. Defeat the evil lurking within the Rubian and let your instance leader return it to me. That is all.");
} }
} }
else else
+1 -1
View File
@@ -54,7 +54,7 @@ function action(mode, type, selection) {
if (status == 0) { if (status == 0) {
if(cm.isEventLeader()) { if(cm.isEventLeader()) {
if(!cm.getEventInstance().isEventTeamTogether()) { if(!cm.getEventInstance().isEventTeamTogether()) {
cm.sendOk("One or more event team members is missing, please wait for them to reach here first."); cm.sendOk("One or more instance team members is missing, please wait for them to reach here first.");
cm.dispose(); cm.dispose();
} }
else if(cm.hasItem(4001106, 30)) { else if(cm.hasItem(4001106, 30)) {
+1 -1
View File
@@ -74,7 +74,7 @@ function action(mode, type, selection) {
advance = true; advance = true;
if(status == 0) { if(status == 0) {
cm.sendNext("Hi there, how is it going? Since you're passing by Amoria, have you heard about the event my brother Amos is hosting? It is the #bAmorian Challenge#k, an event for everyone above level 40.\r\n\r\nThere, you may find the #i4031543# #i4031544# #i4031545# #bWish Tickets#k that can be brought here to redeem prizes."); cm.sendNext("Hi there, how is it going? Since you're passing by Amoria, have you heard about the instance my brother Amos is hosting? It is the #bAmorian Challenge#k, an instance for everyone above level 40.\r\n\r\nThere, you may find the #i4031543# #i4031544# #i4031545# #bWish Tickets#k that can be brought here to redeem prizes.");
} else if(status == 1) { } else if(status == 1) {
var listStr = ""; var listStr = "";
for(var i = 0; i < wishPrizes.length; i++) { for(var i = 0; i < wishPrizes.length; i++) {
+1 -1
View File
@@ -83,7 +83,7 @@ function action(mode, type, selection) {
cm.sendOk("Try using a Super Megaphone or asking your buddies or guild to join!"); cm.sendOk("Try using a Super Megaphone or asking your buddies or guild to join!");
cm.dispose(); cm.dispose();
} else { } else {
cm.sendOk("#e#b<Party Quest: Amorian Challenge>#k#n\r\nI am Amos, hoster of the well-round famed Amorian Challenge. The event consist of many team puzzles, where cooperation is the fundamental key for progress. Team up with other players to attempt for the bonus stage, where many goodies can be obtained at the end of the event. If an all-couple party is formed, they can get even better prizes on the extra bonus stage."); cm.sendOk("#e#b<Party Quest: Amorian Challenge>#k#n\r\nI am Amos, hoster of the well-round famed Amorian Challenge. The instance consist of many team puzzles, where cooperation is the fundamental key for progress. Team up with other players to attempt for the bonus stage, where many goodies can be obtained at the end of the instance. If an all-couple party is formed, they can get even better prizes on the extra bonus stage.");
cm.dispose(); cm.dispose();
} }
} }
+1 -1
View File
@@ -20,7 +20,7 @@
*/ */
/*Jack /*Jack
* *
*@author SharpAceX (Alan) *@author Alan (SharpAceX)
*@author Ronan *@author Ronan
*/ */
importPackage(Packages.server.expeditions); importPackage(Packages.server.expeditions);
+8 -1
View File
@@ -23,11 +23,13 @@
Version Version
|- 1.0 by Jayd |- 1.0 by Jayd
|- 1.1 by Ronan (check job requirements)
*/ */
var status; var status;
var map = 102000003; var map = 102000003;
var job = "Warrior"; var job = "Warrior";
var jobType = 1;
var no = "Come back to me if you decided to be a #b"+job+"#k."; var no = "Come back to me if you decided to be a #b"+job+"#k.";
function start() { function start() {
@@ -52,7 +54,12 @@ function action(mode, type, selection) {
if(status == 0) { if(status == 0) {
if (cm.getJob() == "BEGINNER") { if (cm.getJob() == "BEGINNER") {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?"); if (cm.getLevel() >= 10 && cm.canGetFirstJob(jobType)) {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?");
} else {
cm.sendOk("If you want to be a #b"+job+"#k, train yourself further until you reach #blevel 10, " + cm.getFirstJobStatRequirement(jobType) + "#k.");
cm.dispose();
}
} else { } else {
cm.sendOk("You're much stronger now. Keep training!"); cm.sendOk("You're much stronger now. Keep training!");
cm.dispose(); cm.dispose();
+11 -2
View File
@@ -23,11 +23,14 @@
Version Version
|- 1.0 by Jayd |- 1.0 by Jayd
|- 1.1 by Ronan (check job requirements)
*/ */
var status; var status;
var map = 100000201; var map = 100000201;
var job = "Bowman"; var job = "Bowman";
var jobType = 3;
var no = "Come back to me if you decided to be a #b"+job+"#k.";
function start() { function start() {
status = -1; status = -1;
@@ -36,10 +39,11 @@ function start() {
function action(mode, type, selection) { function action(mode, type, selection) {
if (mode == -1) { if (mode == -1) {
cm.sendOk(no);
cm.dispose(); cm.dispose();
} else { } else {
if (mode == 0 && type > 0) { if (mode == 0 && type > 0) {
cm.sendOk("Come back to me if you decided to be a #b"+job+"#k."); cm.sendOk(no);
cm.dispose(); cm.dispose();
} }
@@ -50,7 +54,12 @@ function action(mode, type, selection) {
if(status == 0) { if(status == 0) {
if (cm.getJob() == "BEGINNER") { if (cm.getJob() == "BEGINNER") {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?"); if (cm.getLevel() >= 10 && cm.canGetFirstJob(jobType)) {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?");
} else {
cm.sendOk("If you want to be a #b"+job+"#k, train yourself further until you reach #blevel 10, " + cm.getFirstJobStatRequirement(jobType) + "#k.");
cm.dispose();
}
} else { } else {
cm.sendOk("You're much stronger now. Keep training!"); cm.sendOk("You're much stronger now. Keep training!");
cm.dispose(); cm.dispose();
+8 -1
View File
@@ -23,11 +23,13 @@
Version Version
|- 1.0 by Jayd |- 1.0 by Jayd
|- 1.1 by Ronan (check job requirements)
*/ */
var status; var status;
var map = 101000003; var map = 101000003;
var job = "Magician"; var job = "Magician";
var jobType = 2;
var no = "Come back to me if you decided to be a #b"+job+"#k."; var no = "Come back to me if you decided to be a #b"+job+"#k.";
function start() { function start() {
@@ -52,7 +54,12 @@ function action(mode, type, selection) {
if(status == 0) { if(status == 0) {
if (cm.getJob() == "BEGINNER") { if (cm.getJob() == "BEGINNER") {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?"); if (cm.getLevel() >= 8 && cm.canGetFirstJob(jobType)) {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?");
} else {
cm.sendOk("If you want to be a #b"+job+"#k, train yourself further until you reach #blevel 8, " + cm.getFirstJobStatRequirement(jobType) + "#k.");
cm.dispose();
}
} else { } else {
cm.sendOk("You're much stronger now. Keep training!"); cm.sendOk("You're much stronger now. Keep training!");
cm.dispose(); cm.dispose();
+8 -1
View File
@@ -23,11 +23,13 @@
Version Version
|- 1.0 by Jayd |- 1.0 by Jayd
|- 1.1 by Ronan (check job requirements)
*/ */
var status; var status;
var map = 103000003; var map = 103000003;
var job = "Thief"; var job = "Thief";
var jobType = 4;
var no = "Come back to me if you decided to be a #b"+job+"#k."; var no = "Come back to me if you decided to be a #b"+job+"#k.";
function start() { function start() {
@@ -52,7 +54,12 @@ function action(mode, type, selection) {
if(status == 0) { if(status == 0) {
if (cm.getJob() == "BEGINNER") { if (cm.getJob() == "BEGINNER") {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?"); if (cm.getLevel() >= 10 && cm.canGetFirstJob(jobType)) {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?");
} else {
cm.sendOk("If you want to be a #b"+job+"#k, train yourself further until you reach #blevel 10, " + cm.getFirstJobStatRequirement(jobType) + "#k.");
cm.dispose();
}
} else { } else {
cm.sendOk("You're much stronger now. Keep training!"); cm.sendOk("You're much stronger now. Keep training!");
cm.dispose(); cm.dispose();
+8 -1
View File
@@ -23,11 +23,13 @@
Version Version
|- 1.0 by Jayd |- 1.0 by Jayd
|- 1.1 by Ronan (check job requirements)
*/ */
var status; var status;
var map = 120000101; var map = 120000101;
var job = "Pirate"; var job = "Pirate";
var jobType = 5;
var no = "Come back to me if you decided to be a #b"+job+"#k."; var no = "Come back to me if you decided to be a #b"+job+"#k.";
function start() { function start() {
@@ -52,7 +54,12 @@ function action(mode, type, selection) {
if(status == 0) { if(status == 0) {
if (cm.getJob() == "BEGINNER") { if (cm.getJob() == "BEGINNER") {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?"); if (cm.getLevel() >= 10 && cm.canGetFirstJob(jobType)) {
cm.sendYesNo("Hey #h #, I can send you to #b#m"+map+"##k if you want to be a #b"+job+"#k. Do you want to go now?");
} else {
cm.sendOk("If you want to be a #b"+job+"#k, train yourself further until you reach #blevel 10, " + cm.getFirstJobStatRequirement(jobType) + "#k.");
cm.dispose();
}
} else { } else {
cm.sendOk("You're much stronger now. Keep training!"); cm.sendOk("You're much stronger now. Keep training!");
cm.dispose(); cm.dispose();
+1 -1
View File
@@ -20,7 +20,7 @@
*/ */
/*Aldol /*Aldol
* *
*@author SharpAceX (Alan) *@author Alan (SharpAceX)
*@author Ronan *@author Ronan
*/ */
importPackage(Packages.server.expeditions); importPackage(Packages.server.expeditions);
+4 -1
View File
@@ -41,7 +41,7 @@ function addFeature(feature) {
function writeFeatureTab_PQs() { function writeFeatureTab_PQs() {
addFeature("HPQ/KPQ/LPQ/LMPQ/OPQ/APQ/EllinPQ/PiratePQ."); addFeature("HPQ/KPQ/LPQ/LMPQ/OPQ/APQ/EllinPQ/PiratePQ.");
addFeature("RnJPQ/HorntailPQ/TreasurePQ/ElnathPQ/HolidayPQ."); addFeature("RnJPQ/HorntailPQ/TreasurePQ/ElnathPQ/HolidayPQ.");
addFeature("CWKPQ as Expedition-based event."); addFeature("CWKPQ as Expedition-based instance.");
addFeature("Scarga/Horntail/Showa/Balrog/Zakum/Pinkbean."); addFeature("Scarga/Horntail/Showa/Balrog/Zakum/Pinkbean.");
addFeature("GuildPQ & queue with multi-lobby systems available."); addFeature("GuildPQ & queue with multi-lobby systems available.");
addFeature("Brand-new PQs: BossRushPQ, CafePQ."); addFeature("Brand-new PQs: BossRushPQ, CafePQ.");
@@ -131,6 +131,7 @@ function writeFeatureTab_MonstersMapsReactors() {
} }
function writeFeatureTab_PQpotentials() { function writeFeatureTab_PQpotentials() {
addFeature("Advanced and well-safe PQ registration system.");
addFeature("Lobby system: Same channel, multiple PQ instances."); addFeature("Lobby system: Same channel, multiple PQ instances.");
addFeature("Exped system: Many parties can join a same instance."); addFeature("Exped system: Many parties can join a same instance.");
addFeature("Guild queue: guild registration for the GPQ."); addFeature("Guild queue: guild registration for the GPQ.");
@@ -144,6 +145,7 @@ function writeFeatureTab_Playerpotentials() {
addFeature("Gain fame by quests."); addFeature("Gain fame by quests.");
addFeature("Pet evolutions functional (not GMS-like)."); addFeature("Pet evolutions functional (not GMS-like).");
addFeature("Reviewed keybinding system."); addFeature("Reviewed keybinding system.");
addFeature("Character slots per world/server-wide.");
} }
function writeFeatureTab_Serverpotentials() { function writeFeatureTab_Serverpotentials() {
@@ -162,6 +164,7 @@ function writeFeatureTab_Serverpotentials() {
addFeature("Pet pickup gives preference to player attacks."); addFeature("Pet pickup gives preference to player attacks.");
addFeature("Channel capacity bar and worlds with capacity check."); addFeature("Channel capacity bar and worlds with capacity check.");
addFeature("Diseases visible for others, even after changing maps."); addFeature("Diseases visible for others, even after changing maps.");
addFeature("Persistent diseases. Players keep their status on login.");
addFeature("Poison damage value visible for other players."); addFeature("Poison damage value visible for other players.");
addFeature("M. book announcer displays info based on demand."); addFeature("M. book announcer displays info based on demand.");
addFeature("Custom jail system."); addFeature("Custom jail system.");
+3
View File
@@ -162,6 +162,9 @@ function writeHeavenMSCommandsLv3() { //GM
addCommand("npc", ""); addCommand("npc", "");
addCommand("face", ""); addCommand("face", "");
addCommand("hair", ""); addCommand("hair", "");
addCommand("startquest", "");
addCommand("completequest", "");
addCommand("resetquest", "");
} }
function writeHeavenMSCommandsLv2() { //JrGM function writeHeavenMSCommandsLv2() { //JrGM
+1
View File
@@ -36,6 +36,7 @@ function writeServerStaff_MapleNext() {
function writeServerStaff_HeavenMS() { function writeServerStaff_HeavenMS() {
addPerson("Ronan", "Developer"); addPerson("Ronan", "Developer");
addPerson("Vcoc", "Freelance Developer"); addPerson("Vcoc", "Freelance Developer");
addPerson("Thora", "Contributor");
setHistory(2015, 2018); setHistory(2015, 2018);
} }
+1 -1
View File
@@ -1,7 +1,7 @@
function enter(pi) { function enter(pi) {
var nex = pi.getEventManager("GuardianNex"); var nex = pi.getEventManager("GuardianNex");
if(nex == null) { if(nex == null) {
pi.message("Guardian Nex event encontered an error and is unavailable."); pi.message("Guardian Nex challenge encountered an error and is unavailable.");
return false; return false;
} }
+1 -1
View File
@@ -37,7 +37,7 @@ function enter(pi) {
return true; return true;
} }
else { else {
pi.message("Make a room available on all EQUIP, USE, SET-UP and ETC inventory to claim an event prize."); pi.message("Make a room available on all EQUIP, USE, SET-UP and ETC inventory to claim an instance prize.");
return false; return false;
} }
} }
+1 -1
View File
@@ -19,7 +19,7 @@
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* Author: Xterminator (Modified by XxOsirisxX) /* Author: Xterminator <Modified by XxOsirisxX>
NPC Name: Roger NPC Name: Roger
Map(s): Maple Road : Lower level of the Training Camp (2) Map(s): Maple Road : Lower level of the Training Camp (2)
Description: Quest - Roger's Apple Description: Quest - Roger's Apple
+64
View File
@@ -0,0 +1,64 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Papulatus - 7103
*/
var status = -1;
function start(mode, type, selection) {
if (mode == -1) {
qm.sendOk("Oh really. Do you need more time? I'm fully confident that you'll help me out before the Time Sphere is formed.");
qm.dispose();
} else {
if(mode == 0 && type > 0) {
qm.sendOk("Oh really. Do you need more time? I'm fully confident that you'll help me out before the Time Sphere is formed.");
qm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
qm.sendYesNo("Only thing we have to do now ...is to make #o8500002# disappear forever... are you ready?");
} else if (status == 1) {
qm.sendNext("I'll explain to you what you need to do from here on out. \r\nTo enter the power-generating room, you'll need to pass either #bForgotten Passage#k or the #bWarped Passage#k. Once you defeat whichever monster that is guarding the passage, you can obtain #b#t4031172:##k, which is needed to enter the power-generating room.");
} else if (status == 2) {
qm.sendNextPrev("Then enter the room through the door in the middle. It's going to be MUCH quieter than you imagined. The Time Sphere should be hidden in a state undetectable in our eyes... but if you seal up the crack in dimension, the #o8500002#, panicking because its exit route is sealed up, will make its appearance there.");
} else if (status == 3) {
if (!qm.haveItem(4031179, 1)) {
if (!qm.canHold(4031179, 1)) {
qm.sendOk("Please have an #rETC slot available#k to start this quest.");
qm.dispose();
return;
}
qm.gainItem(4031179, 1);
}
qm.sendAcceptDecline("Drop the #b#t4031179:##k that I returned to you to seal up whatever crack you see that #o8500002# may have used to enter this dimension in the first place. Then it'll come out of the Time Sphere and show everyone its true appearance. Please, please kill it and then come back. \r\n\r\nCollect #r1 #t4031172:##k\r\nEliminate #r#o8500001##k");
} else if (status == 4) {
qm.forceStartQuest();
qm.dispose();
}
}
}
+2 -2
View File
@@ -40,7 +40,7 @@ function act() {
if(!rm.getReactor().isRecentHitFromAttack()) { if(!rm.getReactor().isRecentHitFromAttack()) {
var prevCombo = eim.getProperty("stage1combo"); var prevCombo = eim.getProperty("stage1combo");
var n = "" + rm.getReactor().getObjectId(); var n = "" + (rm.getReactor().getObjectId() % 1000);
prevCombo += padWithZeroes(n, 3); prevCombo += padWithZeroes(n, 3);
eim.setProperty("stage1combo",prevCombo); eim.setProperty("stage1combo",prevCombo);
@@ -53,7 +53,7 @@ function act() {
} else { //active } else { //active
var prevGuess = "" + eim.getProperty("stage1guess"); var prevGuess = "" + eim.getProperty("stage1guess");
if (prevGuess.length != (3 * (stage + 3))) { if (prevGuess.length != (3 * (stage + 3))) {
var n = "" + rm.getReactor().getObjectId(); var n = "" + (rm.getReactor().getObjectId() % 1000);
prevGuess += padWithZeroes(n, 3); prevGuess += padWithZeroes(n, 3);
eim.setProperty("stage1guess",prevGuess); eim.setProperty("stage1guess",prevGuess);
+2 -2
View File
@@ -42,7 +42,7 @@ function act() {
if(!rm.getReactor().isRecentHitFromAttack()) { if(!rm.getReactor().isRecentHitFromAttack()) {
var prevCombo = eim.getProperty("stage1combo"); var prevCombo = eim.getProperty("stage1combo");
var n = "" + rm.getReactor().getObjectId(); var n = "" + (rm.getReactor().getObjectId() % 1000);
prevCombo += padWithZeroes(n, 3); prevCombo += padWithZeroes(n, 3);
eim.setProperty("stage1combo",prevCombo); eim.setProperty("stage1combo",prevCombo);
@@ -55,7 +55,7 @@ function act() {
} else { //active } else { //active
var prevGuess = "" + eim.getProperty("stage1guess"); var prevGuess = "" + eim.getProperty("stage1guess");
if (prevGuess.length != (3 * (stage + 3))) { if (prevGuess.length != (3 * (stage + 3))) {
var n = "" + rm.getReactor().getObjectId(); var n = "" + (rm.getReactor().getObjectId() % 1000);
prevGuess += padWithZeroes(n, 3); prevGuess += padWithZeroes(n, 3);
eim.setProperty("stage1guess",prevGuess); eim.setProperty("stage1guess",prevGuess);
+2 -2
View File
@@ -39,7 +39,7 @@ function act() {
if (status.equals("display")) { if (status.equals("display")) {
if(!rm.getReactor().isRecentHitFromAttack()) { if(!rm.getReactor().isRecentHitFromAttack()) {
var prevCombo = eim.getProperty("stage1combo"); var prevCombo = eim.getProperty("stage1combo");
var n = "" + rm.getReactor().getObjectId(); var n = "" + (rm.getReactor().getObjectId() % 1000);
prevCombo += padWithZeroes(n, 3); prevCombo += padWithZeroes(n, 3);
eim.setProperty("stage1combo",prevCombo); eim.setProperty("stage1combo",prevCombo);
@@ -52,7 +52,7 @@ function act() {
} else { //active } else { //active
var prevGuess = "" + eim.getProperty("stage1guess"); var prevGuess = "" + eim.getProperty("stage1guess");
if (prevGuess.length != (3 * (stage + 3))) { if (prevGuess.length != (3 * (stage + 3))) {
var n = "" + rm.getReactor().getObjectId(); var n = "" + (rm.getReactor().getObjectId() % 1000);
prevGuess += padWithZeroes(n, 3); prevGuess += padWithZeroes(n, 3);
eim.setProperty("stage1guess",prevGuess); eim.setProperty("stage1guess",prevGuess);
+10 -1
View File
@@ -25,7 +25,6 @@ CREATE TABLE IF NOT EXISTS `accounts` (
`birthday` date NOT NULL DEFAULT '0000-00-00', `birthday` date NOT NULL DEFAULT '0000-00-00',
`banned` tinyint(1) NOT NULL DEFAULT '0', `banned` tinyint(1) NOT NULL DEFAULT '0',
`banreason` text, `banreason` text,
`gm` tinyint(1) NOT NULL DEFAULT '0',
`macs` tinytext, `macs` tinytext,
`nxCredit` int(11) DEFAULT NULL, `nxCredit` int(11) DEFAULT NULL,
`maplePoint` int(11) DEFAULT NULL, `maplePoint` int(11) DEFAULT NULL,
@@ -16474,6 +16473,16 @@ CREATE TABLE IF NOT EXISTS `petignores` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `playerdiseases` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`charid` int(11) NOT NULL,
`disease` int(11) NOT NULL,
`mobskillid` int(11) NOT NULL,
`mobskilllv` int(11) NOT NULL,
`length` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `playernpcs` ( CREATE TABLE IF NOT EXISTS `playernpcs` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(13) NOT NULL, `name` varchar(13) NOT NULL,
+5
View File
@@ -19823,6 +19823,11 @@ USE `heavenms`;
(1110100, 4001369, 1, 1, 28259, 40000), (1110100, 4001369, 1, 1, 28259, 40000),
(1210101, 4001370, 1, 1, 28260, 40000), (1210101, 4001370, 1, 1, 28260, 40000),
(1110101, 4001371, 1, 1, 28261, 40000), (1110101, 4001371, 1, 1, 28261, 40000),
(2130100, 4001368, 1, 1, 28262, 40000),
(2110200, 4001369, 1, 1, 28262, 40000),
(1110100, 4001370, 1, 1, 28262, 40000),
(1210101, 4001371, 1, 1, 28262, 40000),
(1110101, 4001367, 1, 1, 28262, 40000),
(3300003, 4001317, 1, 1, 2326, 20000), (3300003, 4001317, 1, 1, 2326, 20000),
(1210102, 4001364, 1, 1, 28192, 80000), (1210102, 4001364, 1, 1, 28192, 80000),
(1120100, 4001365, 1, 1, 28192, 80000), (1120100, 4001365, 1, 1, 28192, 80000),
+111 -24
View File
@@ -155,6 +155,7 @@ import constants.skills.Swordsman;
import constants.skills.ThunderBreaker; import constants.skills.ThunderBreaker;
import net.server.channel.handlers.PartyOperationHandler; import net.server.channel.handlers.PartyOperationHandler;
import scripting.item.ItemScriptManager; import scripting.item.ItemScriptManager;
import server.life.MobSkillFactory;
import server.maps.MapleMapItem; import server.maps.MapleMapItem;
import net.server.audit.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
@@ -1370,6 +1371,35 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
eventAfterChangedMap(this.getMapId()); eventAfterChangedMap(this.getMapId());
} }
public void forceChangeMap(final MapleMap target, final MaplePortal pto) {
// will actually enter the map given as parameter, regardless of being an eventmap or whatnot
canWarpCounter++;
eventChangedMap(999999999);
EventInstanceManager mapEim = target.getEventInstance();
if(mapEim != null) {
EventInstanceManager playerEim = this.getEventInstance();
if(playerEim != null) {
playerEim.exitPlayer(this);
if(playerEim.getPlayerCount() == 0) {
playerEim.dispose();
}
}
mapEim.registerPlayer(this);
}
MapleMap to = getWarpMap(target.getId());
changeMapInternal(to, pto.getPosition(), MaplePacketCreator.getWarpToMap(to, pto.getId(), this));
canWarpMap = false;
canWarpCounter--;
if(canWarpCounter == 0) canWarpMap = true;
eventAfterChangedMap(this.getMapId());
}
private boolean buffMapProtection() { private boolean buffMapProtection() {
effLock.lock(); effLock.lock();
chrLock.lock(); chrLock.lock();
@@ -2073,6 +2103,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setInt(1, cid); ps.setInt(1, cid);
ps.executeUpdate(); ps.executeUpdate();
} }
try (PreparedStatement ps = con.prepareStatement("DELETE FROM playerdiseases WHERE charid = ?")) {
ps.setInt(1, cid);
ps.executeUpdate();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM area_info WHERE charid = ?")) { try (PreparedStatement ps = con.prepareStatement("DELETE FROM area_info WHERE charid = ?")) {
ps.setInt(1, cid); ps.setInt(1, cid);
ps.executeUpdate(); ps.executeUpdate();
@@ -2359,31 +2393,34 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
long expTime = curTime + di.getValue().getLeft(); long expTime = curTime + di.getValue().getLeft();
diseaseExpires.put(di.getKey(), expTime); diseaseExpires.put(di.getKey(), expTime);
diseases.put(di.getKey(), new Pair<>(new MapleDiseaseValueHolder(curTime, expTime), di.getValue().getRight())); diseases.put(di.getKey(), new Pair<>(new MapleDiseaseValueHolder(curTime, di.getValue().getLeft()), di.getValue().getRight()));
} }
} finally { } finally {
chrLock.unlock(); chrLock.unlock();
} }
} }
public void announceDiseases(MapleClient c) { public void announceDiseases() {
Set<Entry<MapleDisease, Pair<MapleDiseaseValueHolder, MobSkill>>> chrDiseases;
chrLock.lock(); chrLock.lock();
try { try {
// Poison damage visibility and diseases status visibility, extended through map transitions thanks to Ronan // Poison damage visibility and diseases status visibility, extended through map transitions thanks to Ronan
if(!this.isLoggedinWorld()) return; if(!this.isLoggedinWorld()) return;
for(Entry<MapleDisease, Pair<MapleDiseaseValueHolder, MobSkill>> di : diseases.entrySet()) { chrDiseases = new LinkedHashSet<>(diseases.entrySet());
MapleDisease disease = di.getKey();
MobSkill skill = di.getValue().getRight();
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(disease, Integer.valueOf(skill.getX())));
if(disease != MapleDisease.SLOW) c.announce(MaplePacketCreator.giveForeignDebuff(id, debuff, skill));
else c.announce(MaplePacketCreator.giveForeignSlowDebuff(id, debuff, skill));
}
} finally { } finally {
chrLock.unlock(); chrLock.unlock();
} }
for(Entry<MapleDisease, Pair<MapleDiseaseValueHolder, MobSkill>> di : chrDiseases) {
MapleDisease disease = di.getKey();
MobSkill skill = di.getValue().getRight();
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(disease, Integer.valueOf(skill.getX())));
if(disease != MapleDisease.SLOW) map.broadcastMessage(MaplePacketCreator.giveForeignDebuff(id, debuff, skill));
else map.broadcastMessage(MaplePacketCreator.giveForeignSlowDebuff(id, debuff, skill));
}
} }
public void giveDebuff(final MapleDisease disease, MobSkill skill) { public void giveDebuff(final MapleDisease disease, MobSkill skill) {
@@ -6276,11 +6313,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} }
rs.close(); rs.close();
ps.close(); ps.close();
ps = con.prepareStatement("SELECT name FROM accounts WHERE id = ?", Statement.RETURN_GENERATED_KEYS); ps = con.prepareStatement("SELECT name, characterslots FROM accounts WHERE id = ?", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, ret.accountid); ps.setInt(1, ret.accountid);
rs = ps.executeQuery(); rs = ps.executeQuery();
if (rs.next()) { if (rs.next()) {
ret.getClient().setAccountName(rs.getString("name")); MapleClient retClient = ret.getClient();
retClient.setAccountName(rs.getString("name"));
retClient.setCharacterSlots(rs.getByte("characterslots"));
} }
rs.close(); rs.close();
ps.close(); ps.close();
@@ -6348,7 +6388,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
try (ResultSet rsProgress = pse.executeQuery()) { try (ResultSet rsProgress = pse.executeQuery()) {
while(rsProgress.next()) { while(rsProgress.next()) {
MapleQuestStatus status = loadedQuestStatus.get(rsProgress.getInt("queststatusid")); MapleQuestStatus status = loadedQuestStatus.get(rsProgress.getInt("queststatusid"));
status.setProgress(rsProgress.getInt("progressid"), rsProgress.getString("progress")); if(status != null) {
status.setProgress(rsProgress.getInt("progressid"), rsProgress.getString("progress"));
}
} }
} }
} }
@@ -6358,7 +6400,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
try (ResultSet rsMedalMaps = pse.executeQuery()) { try (ResultSet rsMedalMaps = pse.executeQuery()) {
while(rsMedalMaps.next()) { while(rsMedalMaps.next()) {
MapleQuestStatus status = loadedQuestStatus.get(rsMedalMaps.getInt("queststatusid")); MapleQuestStatus status = loadedQuestStatus.get(rsMedalMaps.getInt("queststatusid"));
status.addMedalMap(rsMedalMaps.getInt("mapid")); if(status != null) {
status.addMedalMap(rsMedalMaps.getInt("mapid"));
}
} }
} }
} }
@@ -6391,6 +6435,29 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setInt(1, ret.getId()); ps.setInt(1, ret.getId());
ps.executeUpdate(); ps.executeUpdate();
ps.close(); ps.close();
Map<MapleDisease, Pair<Long, MobSkill>> loadedDiseases = new LinkedHashMap<>();
ps = con.prepareStatement("SELECT * FROM playerdiseases WHERE charid = ?");
ps.setInt(1, ret.getId());
rs = ps.executeQuery();
while (rs.next()) {
final MapleDisease disease = MapleDisease.ordinal(rs.getInt("disease"));
if(disease == MapleDisease.NULL) continue;
final int skillid = rs.getInt("mobskillid"), skilllv = rs.getInt("mobskilllv");
final long length = rs.getInt("length");
MobSkill ms = MobSkillFactory.getMobSkill(skillid, skilllv);
if(ms != null) {
loadedDiseases.put(disease, new Pair<>(length, ms));
}
}
rs.close();
ps.close();
ps = con.prepareStatement("DELETE FROM playerdiseases WHERE charid = ?");
ps.setInt(1, ret.getId());
ps.executeUpdate();
ps.close();
if(!loadedDiseases.isEmpty()) Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(ret.id, loadedDiseases);
ps = con.prepareStatement("SELECT * FROM skillmacros WHERE characterid = ?"); ps = con.prepareStatement("SELECT * FROM skillmacros WHERE characterid = ?");
ps.setInt(1, charid); ps.setInt(1, charid);
rs = ps.executeQuery(); rs = ps.executeQuery();
@@ -6921,8 +6988,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public synchronized void saveCooldowns() { public synchronized void saveCooldowns() {
List<PlayerCoolDownValueHolder> listcd = getAllCooldowns(); List<PlayerCoolDownValueHolder> listcd = getAllCooldowns();
if (listcd.size() > 0) { if (!listcd.isEmpty()) {
try { try {
Connection con = DatabaseConnection.getConnection(); Connection con = DatabaseConnection.getConnection();
deleteWhereCharacterId(con, "DELETE FROM cooldowns WHERE charid = ?"); deleteWhereCharacterId(con, "DELETE FROM cooldowns WHERE charid = ?");
@@ -6942,6 +7009,33 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
se.printStackTrace(); se.printStackTrace();
} }
} }
Map<MapleDisease, Pair<Long, MobSkill>> listds = getAllDiseases();
if (!listds.isEmpty()) {
try {
Connection con = DatabaseConnection.getConnection();
deleteWhereCharacterId(con, "DELETE FROM playerdiseases WHERE charid = ?");
try (PreparedStatement ps = con.prepareStatement("INSERT INTO playerdiseases (charid, disease, mobskillid, mobskilllv, length) VALUES (?, ?, ?, ?, ?)")) {
ps.setInt(1, getId());
for (Entry<MapleDisease, Pair<Long, MobSkill>> e : listds.entrySet()) {
ps.setInt(2, e.getKey().ordinal());
MobSkill ms = e.getValue().getRight();
ps.setInt(3, ms.getSkillId());
ps.setInt(4, ms.getSkillLevel());
ps.setInt(5, e.getValue().getLeft().intValue());
ps.addBatch();
}
ps.executeBatch();
}
con.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
} }
public void saveGuildStatus() { public void saveGuildStatus() {
@@ -7454,13 +7548,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
psf.close(); psf.close();
ps.close(); ps.close();
ps = con.prepareStatement("UPDATE accounts SET gm = ? WHERE id = ?");
ps.setInt(1, gmLevel > 1 ? 1 : 0);
ps.setInt(2, client.getAccID());
ps.executeUpdate();
ps.close();
con.commit(); con.commit();
con.setAutoCommit(true); con.setAutoCommit(true);
+17 -3
View File
@@ -516,13 +516,13 @@ public class MapleClient {
ResultSet rs = null; ResultSet rs = null;
try { try {
con = DatabaseConnection.getConnection(); con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT id, password, salt, gender, banned, gm, pin, pic, characterslots, tos FROM accounts WHERE name = ?"); ps = con.prepareStatement("SELECT id, password, salt, gender, banned, pin, pic, characterslots, tos FROM accounts WHERE name = ?");
ps.setString(1, login); ps.setString(1, login);
rs = ps.executeQuery(); rs = ps.executeQuery();
if (rs.next()) { if (rs.next()) {
boolean banned = (rs.getByte("banned") == 1); boolean banned = (rs.getByte("banned") == 1);
accId = rs.getInt("id"); accId = rs.getInt("id");
gmlevel = rs.getInt("gm"); gmlevel = 0;
pin = rs.getString("pin"); pin = rs.getString("pin");
pic = rs.getString("pic"); pic = rs.getString("pic");
gender = rs.getByte("gender"); gender = rs.getByte("gender");
@@ -796,7 +796,6 @@ public class MapleClient {
player.setDisconnectedFromChannelWorld(); player.setDisconnectedFromChannelWorld();
player.notifyMapTransferToPartner(-1); player.notifyMapTransferToPartner(-1);
player.cancelAllBuffs(true); player.cancelAllBuffs(true);
player.cancelAllDebuffs();
player.closePlayerInteractions(); player.closePlayerInteractions();
QuestScriptManager.getInstance().dispose(this); QuestScriptManager.getInstance().dispose(this);
@@ -845,6 +844,7 @@ public class MapleClient {
removePlayer(); removePlayer();
player.saveCooldowns(); player.saveCooldowns();
player.cancelAllDebuffs();
player.saveCharToDB(true); player.saveCharToDB(true);
clear(); clear();
@@ -927,6 +927,7 @@ public class MapleClient {
//getChannelServer().removePlayer(player); already being done //getChannelServer().removePlayer(player); already being done
player.saveCooldowns(); player.saveCooldowns();
player.cancelAllDebuffs();
player.saveCharToDB(true); player.saveCharToDB(true);
if (player != null) {//no idea, occur :( if (player != null) {//no idea, occur :(
player.empty(false); player.empty(false);
@@ -936,6 +937,7 @@ public class MapleClient {
getChannelServer().removePlayer(player); getChannelServer().removePlayer(player);
player.saveCooldowns(); player.saveCooldowns();
player.cancelAllDebuffs();
player.saveCharToDB(); player.saveCharToDB();
} }
} }
@@ -1191,9 +1193,21 @@ public class MapleClient {
} }
} }
public short getAvailableCharacterSlots() {
return (short) Math.max(0, characterSlots - Server.getInstance().getAccountCharacterCount(accId));
}
public short getAvailableCharacterWorldSlots() {
return (short) Math.max(0, characterSlots - Server.getInstance().getAccountWorldCharacterCount(accId, world));
}
public short getCharacterSlots() { public short getCharacterSlots() {
return characterSlots; return characterSlots;
} }
public void setCharacterSlots(byte slots) {
characterSlots = slots;
}
public synchronized boolean gainCharacterSlot() { public synchronized boolean gainCharacterSlot() {
if (characterSlots < 15) { if (characterSlots < 15) {
+11 -1
View File
@@ -21,6 +21,9 @@
*/ */
package client; package client;
import java.util.ArrayList;
import java.util.List;
public enum MapleDisease { public enum MapleDisease {
NULL(0x0), NULL(0x0),
SLOW(0x1), SLOW(0x1),
@@ -55,5 +58,12 @@ public enum MapleDisease {
public boolean isFirst() { public boolean isFirst() {
return first; return first;
} }
public static MapleDisease ordinal(int ord) {
try {
return MapleDisease.values()[ord];
} catch (IndexOutOfBoundsException io) {
return NULL;
}
}
} }
+67 -1
View File
@@ -1201,7 +1201,7 @@ public class Commands {
player.dropMessage(5, "Player '" + victim.getName() + "' is at channel " + victim.getClient().getChannel() + "."); player.dropMessage(5, "Player '" + victim.getName() + "' is at channel " + victim.getClient().getChannel() + ".");
} else { } else {
MapleMap map = victim.getMap(); MapleMap map = victim.getMap();
player.changeMap(map, map.findClosestPortal(victim.getPosition())); player.forceChangeMap(map, map.findClosestPortal(victim.getPosition()));
} }
} else { } else {
player.dropMessage(6, "Unknown player."); player.dropMessage(6, "Unknown player.");
@@ -2417,6 +2417,72 @@ public class Commands {
} catch(Exception e) {} } catch(Exception e) {}
break; break;
case "startquest":
if (sub.length < 2){
player.yellowMessage("Syntax: !startquest <questid>");
break;
}
int questid = Integer.parseInt(sub[1]);
if (player.getQuestStatus(questid) == 0) {
MapleQuest quest = MapleQuest.getInstance(questid);
if (quest != null) {
int npcid = quest.getNpcRequirement(false);
quest.forceStart(player, npcid);
player.dropMessage(5, "QUEST " + questid + " started.");
} else {
player.dropMessage(5, "QUESTID " + questid + " is invalid.");
}
} else {
player.dropMessage(5, "QUESTID " + questid + " already started/completed.");
}
break;
case "completequest":
if (sub.length < 2){
player.yellowMessage("Syntax: !completequest <questid>");
break;
}
int questId = Integer.parseInt(sub[1]);
if (player.getQuestStatus(questId) == 1) {
MapleQuest quest = MapleQuest.getInstance(questId);
if (quest != null) {
int npcid = quest.getNpcRequirement(true);
quest.forceComplete(player, npcid);
player.dropMessage(5, "QUEST " + questId + " completed.");
} else { // should not occur
player.dropMessage(5, "QUESTID " + questId + " is invalid.");
}
} else {
player.dropMessage(5, "QUESTID " + questId + " not started or already completed.");
}
break;
case "resetquest":
if (sub.length < 2){
player.yellowMessage("Syntax: !resetquest <questid>");
break;
}
int questid_ = Integer.parseInt(sub[1]);
if (player.getQuestStatus(questid_) != 0) {
MapleQuest quest = MapleQuest.getInstance(questid_);
if (quest != null) {
quest.reset(player);
player.dropMessage(5, "QUEST " + questid_ + " reseted.");
} else { // should not occur
player.dropMessage(5, "QUESTID " + questid_ + " is invalid.");
}
}
break;
default: default:
return false; return false;
} }
+5
View File
@@ -25,6 +25,7 @@ import client.MapleSkinColor;
import client.inventory.Item; import client.inventory.Item;
import client.inventory.MapleInventory; import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType; import client.inventory.MapleInventoryType;
import constants.ServerConstants;
import net.server.Server; import net.server.Server;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
@@ -36,6 +37,10 @@ import tools.MaplePacketCreator;
public abstract class CharacterFactory { public abstract class CharacterFactory {
protected synchronized static int createNewCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, CharacterFactoryRecipe recipe) { protected synchronized static int createNewCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, CharacterFactoryRecipe recipe) {
if (ServerConstants.COLLECTIVE_CHARSLOT ? c.getAvailableCharacterSlots() <= 0 : c.getAvailableCharacterWorldSlots() <= 0) {
return -3;
}
if (!MapleCharacter.canCreateChar(name)) { if (!MapleCharacter.canCreateChar(name)) {
return -1; return -1;
} }
+1 -1
View File
@@ -470,7 +470,7 @@ public class Equip extends Item {
lvupStr += "+UPGSLOT "; lvupStr += "+UPGSLOT ";
} }
showLevelupMessage(showStr, c); // thx to Polaris dev team ! showLevelupMessage(showStr, c); // thanks to Polaris dev team !
c.getPlayer().dropMessage(6, lvupStr); c.getPlayer().dropMessage(6, lvupStr);
c.announce(MaplePacketCreator.showEquipmentLevelUp()); c.announce(MaplePacketCreator.showEquipmentLevelUp());
+1
View File
@@ -32,6 +32,7 @@ public class ServerConstants {
public static final boolean AUTOMATIC_REGISTER = true; //Automatically register players when they login with a nonexistent username. public static final boolean AUTOMATIC_REGISTER = true; //Automatically register players when they login with a nonexistent username.
public static final boolean BCRYPT_MIGRATION = true; //Performs a migration from old SHA-1 and SHA-512 password to bcrypt. public static final boolean BCRYPT_MIGRATION = true; //Performs a migration from old SHA-1 and SHA-512 password to bcrypt.
public static final boolean COLLECTIVE_CHARSLOT = false; //Available character slots are contabilized globally rather than per world server.
//Ip Configuration //Ip Configuration
public static String HOST; public static String HOST;
+44 -7
View File
@@ -100,6 +100,7 @@ public class Server {
private final Properties subnetInfo = new Properties(); private final Properties subnetInfo = new Properties();
private static Server instance = null; private static Server instance = null;
private final Map<Integer, Set<Integer>> accountChars = new HashMap<>(); private final Map<Integer, Set<Integer>> accountChars = new HashMap<>();
private final Map<Integer, Short> accountCharacterCount = new HashMap<>();
private final Map<Integer, Integer> worldChars = new HashMap<>(); private final Map<Integer, Integer> worldChars = new HashMap<>();
private final Map<String, Integer> transitioningChars = new HashMap<>(); private final Map<String, Integer> transitioningChars = new HashMap<>();
private List<Pair<Integer, String>> worldRecommendedList = new LinkedList<>(); private List<Pair<Integer, String>> worldRecommendedList = new LinkedList<>();
@@ -601,9 +602,7 @@ public class Server {
MapleClient c = processDiseaseAnnounceClients.remove(0); MapleClient c = processDiseaseAnnounceClients.remove(0);
MapleCharacter player = c.getPlayer(); MapleCharacter player = c.getPlayer();
if(player != null && player.isLoggedinWorld()) { if(player != null && player.isLoggedinWorld()) {
for(MapleCharacter chr : player.getMap().getCharacters()) { player.announceDiseases();
chr.announceDiseases(c);
}
} }
} }
@@ -1089,6 +1088,32 @@ public class Server {
} }
} }
public short getAccountCharacterCount(Integer accountid) {
lgnRLock.lock();
try {
return accountCharacterCount.get(accountid);
} finally {
lgnRLock.unlock();
}
}
public short getAccountWorldCharacterCount(Integer accountid, Integer worldid) {
lgnRLock.lock();
try {
short count = 0;
for(Integer chr : accountChars.get(accountid)) {
if(worldChars.get(chr).equals(worldid)) {
count++;
}
}
return count;
} finally {
lgnRLock.unlock();
}
}
private Set<Integer> getAccountCharacterEntries(Integer accountid) { private Set<Integer> getAccountCharacterEntries(Integer accountid) {
lgnRLock.lock(); lgnRLock.lock();
try { try {
@@ -1115,6 +1140,8 @@ public class Server {
lgnWLock.lock(); lgnWLock.lock();
try { try {
accountCharacterCount.put(accountid, (short)(accountCharacterCount.get(accountid) + 1));
Set<Integer> accChars = accountChars.get(accountid); Set<Integer> accChars = accountChars.get(accountid);
accChars.add(chrid); accChars.add(chrid);
@@ -1132,6 +1159,8 @@ public class Server {
public void deleteCharacterEntry(Integer accountid, Integer chrid) { public void deleteCharacterEntry(Integer accountid, Integer chrid) {
lgnWLock.lock(); lgnWLock.lock();
try { try {
accountCharacterCount.put(accountid, (short)(accountCharacterCount.get(accountid) - 1));
Set<Integer> accChars = accountChars.get(accountid); Set<Integer> accChars = accountChars.get(accountid);
accChars.remove(chrid); accChars.remove(chrid);
@@ -1169,6 +1198,7 @@ public class Server {
public void deleteAccountEntry(Integer accountid) { is this even a thing? public void deleteAccountEntry(Integer accountid) { is this even a thing?
lgnWLock.lock(); lgnWLock.lock();
try { try {
accountCharacterCount.remove(accountid);
accountChars.remove(accountid); accountChars.remove(accountid);
} finally { } finally {
lgnWLock.unlock(); lgnWLock.unlock();
@@ -1190,6 +1220,7 @@ public class Server {
List<MapleCharacter> wchars = w.getAccountCharactersView(accountId); List<MapleCharacter> wchars = w.getAccountCharactersView(accountId);
if(wchars == null) { if(wchars == null) {
if(!accountChars.containsKey(accountId)) { if(!accountChars.containsKey(accountId)) {
accountCharacterCount.put(accountId, (short) 0);
accountChars.put(accountId, new HashSet<Integer>()); // not advisable at all to write on the map on a read-protected environment accountChars.put(accountId, new HashSet<Integer>()); // not advisable at all to write on the map on a read-protected environment
} // yet it's known there's no problem since no other point in the source does } // yet it's known there's no problem since no other point in the source does
} else if(!wchars.isEmpty()) { // this action. } else if(!wchars.isEmpty()) { // this action.
@@ -1206,7 +1237,8 @@ public class Server {
return new Pair<>(new Pair<>(chrTotal, lastwchars), accChars); return new Pair<>(new Pair<>(chrTotal, lastwchars), accChars);
} }
private static List<List<MapleCharacter>> loadAccountCharactersViewFromDb(int accId, int wlen) { private static Pair<Short, List<List<MapleCharacter>>> loadAccountCharactersViewFromDb(int accId, int wlen) {
short characterCount = 0;
List<List<MapleCharacter>> wchars = new ArrayList<>(wlen); List<List<MapleCharacter>> wchars = new ArrayList<>(wlen);
for(int i = 0; i < wlen; i++) wchars.add(i, new LinkedList<MapleCharacter>()); for(int i = 0; i < wlen; i++) wchars.add(i, new LinkedList<MapleCharacter>());
@@ -1231,8 +1263,10 @@ public class Server {
ps.setInt(1, accId); ps.setInt(1, accId);
try (ResultSet rs = ps.executeQuery()) { try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { while (rs.next()) {
characterCount++;
int cworld = rs.getByte("world"); int cworld = rs.getByte("world");
if(cworld >= wlen) break; if(cworld >= wlen) continue;
if(cworld > curWorld) { if(cworld > curWorld) {
wchars.add(curWorld, chars); wchars.add(curWorld, chars);
@@ -1253,7 +1287,7 @@ public class Server {
sqle.printStackTrace(); sqle.printStackTrace();
} }
return wchars; return new Pair<>(characterCount, wchars);
} }
public void loadAccountCharacters(MapleClient c) { public void loadAccountCharacters(MapleClient c) {
@@ -1300,10 +1334,13 @@ public class Server {
private int loadAccountCharactersView(Integer accId, int gmLevel, int fromWorldid) { // returns the maximum gmLevel found private int loadAccountCharactersView(Integer accId, int gmLevel, int fromWorldid) { // returns the maximum gmLevel found
List<World> wlist = this.getWorlds(); List<World> wlist = this.getWorlds();
List<List<MapleCharacter>> accChars = loadAccountCharactersViewFromDb(accId, wlist.size()); Pair<Short, List<List<MapleCharacter>>> accCharacters = loadAccountCharactersViewFromDb(accId, wlist.size());
lgnWLock.lock(); lgnWLock.lock();
try { try {
List<List<MapleCharacter>> accChars = accCharacters.getRight();
accountCharacterCount.put(accId, accCharacters.getLeft());
Set<Integer> chars = accountChars.get(accId); Set<Integer> chars = accountChars.get(accId);
if(chars == null) { if(chars == null) {
chars = new HashSet<>(5); chars = new HashSet<>(5);
@@ -75,6 +75,7 @@ public enum MonitoredLockType {
EM_LOBBY, EM_LOBBY,
EM_QUEUE, EM_QUEUE,
EM_SCHDL, EM_SCHDL,
EM_START,
CASHSHOP, CASHSHOP,
VISITOR_PSHOP, VISITOR_PSHOP,
STORAGE, STORAGE,
@@ -37,6 +37,11 @@ public final class OwlWarpHandler extends AbstractMaplePacketHandler {
int ownerid = slea.readInt(); int ownerid = slea.readInt();
int mapid = slea.readInt(); int mapid = slea.readInt();
if(ownerid == c.getPlayer().getId()) {
c.announce(MaplePacketCreator.serverNotice(1, "You cannot visit your own shop."));
return;
}
MapleHiredMerchant hm = c.getWorldServer().getHiredMerchant(ownerid); // if both hired merchant and player shop is on the same map MapleHiredMerchant hm = c.getWorldServer().getHiredMerchant(ownerid); // if both hired merchant and player shop is on the same map
MaplePlayerShop ps; MaplePlayerShop ps;
if(hm == null || hm.getMapId() != mapid || !hm.hasItem(c.getPlayer().getOwlSearch())) { if(hm == null || hm.getMapId() != mapid || !hm.hasItem(c.getPlayer().getOwlSearch())) {
@@ -27,6 +27,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
import net.server.PlayerBuffValueHolder; import net.server.PlayerBuffValueHolder;
@@ -90,6 +91,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
c.setCharacterSlots((byte) player.getClient().getCharacterSlots());
player.newClient(c); player.newClient(c);
} }
if (player == null) { //If you are still getting null here then please just uninstall the game >.>, we dont need you fucking with the logs if (player == null) { //If you are still getting null here then please just uninstall the game >.>, we dont need you fucking with the logs
@@ -275,16 +277,6 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
c.announce(MaplePacketCreator.enableReport()); c.announce(MaplePacketCreator.enableReport());
player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1); player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1);
player.checkBerserk(player.isHidden()); player.checkBerserk(player.isHidden());
player.buffExpireTask();
player.diseaseExpireTask();
player.skillCooldownTask();
player.expirationTask();
player.questExpirationTask();
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
player.createDragon();
}
player.commitExcludedItems();
if (newcomer){ if (newcomer){
/* /*
@@ -295,12 +287,31 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
if (player.isGM()){ if (player.isGM()){
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.earnTitleMessage((player.gmLevel() < 6 ? "GM " : "Admin ") + player.getName() + " has logged in")); Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.earnTitleMessage((player.gmLevel() < 6 ? "GM " : "Admin ") + player.getName() + " has logged in"));
} }
if(diseases != null) {
for(Entry<MapleDisease, Pair<Long, MobSkill>> e : diseases.entrySet()) {
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(e.getKey(), Integer.valueOf(e.getValue().getRight().getX())));
c.announce(MaplePacketCreator.giveDebuff(debuff, e.getValue().getRight()));
}
player.announceDiseases();
}
} else { } else {
if(player.isRidingBattleship()) { if(player.isRidingBattleship()) {
player.announceBattleshipHp(); player.announceBattleshipHp();
} }
} }
player.buffExpireTask();
player.diseaseExpireTask();
player.skillCooldownTask();
player.expirationTask();
player.questExpirationTask();
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
player.createDragon();
}
player.commitExcludedItems();
showDueyNotification(c, player); showDueyNotification(c, player);
if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask(); if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask();
@@ -39,8 +39,8 @@ public final class ScriptedItemHandler extends AbstractMaplePacketHandler {
@Override @Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
slea.readInt(); // trash stamp (thx rmzero) slea.readInt(); // trash stamp (thanks rmzero)
short itemSlot = slea.readShort(); // item sl0t (thx rmzero) short itemSlot = slea.readShort(); // item slot (thanks rmzero)
int itemId = slea.readInt(); // itemId int itemId = slea.readInt(); // itemId
scriptedItem info = ii.getScriptedItemInfo(itemId); scriptedItem info = ii.getScriptedItemInfo(itemId);
if (info == null) return; if (info == null) return;
@@ -34,6 +34,7 @@ import client.inventory.ModifyInventory;
import constants.ItemConstants; import constants.ItemConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
import client.inventory.manipulator.MapleInventoryManipulator; import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
@@ -72,10 +73,17 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
Item scroll = useInventory.getItem(slot); Item scroll = useInventory.getItem(slot);
Item wscroll = null; Item wscroll = null;
if (((Equip) toScroll).getUpgradeSlots() < 1 && !ItemConstants.isCleanSlate(scroll.getItemId())) { if (ItemConstants.isCleanSlate(scroll.getItemId())) {
Map<String, Integer> eqStats = ii.getEquipStats(scroll.getItemId());
if (eqStats == null || eqStats.get("tuc") == 0) {
c.announce(MaplePacketCreator.getInventoryFull());
return;
}
} else if (((Equip) toScroll).getUpgradeSlots() < 1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
return; return;
} }
List<Integer> scrollReqs = ii.getScrollReqs(scroll.getItemId()); List<Integer> scrollReqs = ii.getScrollReqs(scroll.getItemId());
if (scrollReqs.size() > 0 && !scrollReqs.contains(toScroll.getItemId())) { if (scrollReqs.size() > 0 && !scrollReqs.contains(toScroll.getItemId())) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
@@ -27,7 +27,6 @@ import java.sql.SQLException;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
import net.server.world.World; import net.server.world.World;
import tools.LogHelper;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.FilePrinter; import tools.FilePrinter;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
@@ -42,7 +41,8 @@ import java.sql.Connection;
* @author Matze * @author Matze
*/ */
public final class WhisperHandler extends AbstractMaplePacketHandler { public final class WhisperHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
byte mode = slea.readByte(); byte mode = slea.readByte();
if (mode == 6) { // whisper if (mode == 6) { // whisper
@@ -92,7 +92,7 @@ public final class WhisperHandler extends AbstractMaplePacketHandler {
} else { } else {
c.announce(MaplePacketCreator.getFindReply(victim.getName(), victim.getMap().getId(), 1)); c.announce(MaplePacketCreator.getFindReply(victim.getName(), victim.getMap().getId(), 1));
} }
} else { // not found } else if (c.getPlayer().gmLevel() > 1) { // not found
try { try {
Connection con = DatabaseConnection.getConnection(); Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT gm FROM characters WHERE name = ?"); PreparedStatement ps = con.prepareStatement("SELECT gm FROM characters WHERE name = ?");
@@ -116,6 +116,8 @@ public final class WhisperHandler extends AbstractMaplePacketHandler {
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
} else {
c.announce(MaplePacketCreator.getWhisperReply(recipient, (byte) 0));
} }
} else if (mode == 0x44) { } else if (mode == 0x44) {
//Buddy find? //Buddy find?
+36 -25
View File
@@ -117,14 +117,16 @@ public class MapleGuild {
return; return;
} }
Set<Integer> chs = Server.getInstance().getOpenChannels(world); Set<Integer> chs = Server.getInstance().getOpenChannels(world);
if (notifications.keySet().size() != chs.size()) { synchronized (notifications) {
notifications.clear(); if (notifications.keySet().size() != chs.size()) {
for (Integer ch : chs) { notifications.clear();
notifications.put(ch, new LinkedList<Integer>()); for (Integer ch : chs) {
} notifications.put(ch, new LinkedList<Integer>());
} else { }
for (List<Integer> l : notifications.values()) { } else {
l.clear(); for (List<Integer> l : notifications.values()) {
l.clear();
}
} }
} }
@@ -134,7 +136,11 @@ public class MapleGuild {
if (!mgc.isOnline()) { if (!mgc.isOnline()) {
continue; continue;
} }
List<Integer> chl = notifications.get(mgc.getChannel());
List<Integer> chl;
synchronized (notifications) {
chl = notifications.get(mgc.getChannel());
}
if (chl != null) chl.add(mgc.getId()); if (chl != null) chl.add(mgc.getId());
//Unable to connect to Channel... error was here //Unable to connect to Channel... error was here
} }
@@ -279,26 +285,31 @@ public class MapleGuild {
} }
public void broadcast(final byte[] packet, int exceptionId, BCOp bcop) { public void broadcast(final byte[] packet, int exceptionId, BCOp bcop) {
synchronized (notifications) { membersLock.lock(); // membersLock awareness thanks to ProjectNano dev team
if (bDirty) { try {
buildNotifications(); synchronized (notifications) {
} if (bDirty) {
try { buildNotifications();
for (Integer b : Server.getInstance().getOpenChannels(world)) { }
if (notifications.get(b).size() > 0) { try {
if (bcop == BCOp.DISBAND) { for (Integer b : Server.getInstance().getOpenChannels(world)) {
Server.getInstance().getWorld(world).setGuildAndRank(notifications.get(b), 0, 5, exceptionId); if (notifications.get(b).size() > 0) {
} else if (bcop == BCOp.EMBLEMCHANGE) { if (bcop == BCOp.DISBAND) {
Server.getInstance().getWorld(world).changeEmblem(this.id, notifications.get(b), new MapleGuildSummary(this)); Server.getInstance().getWorld(world).setGuildAndRank(notifications.get(b), 0, 5, exceptionId);
} else { } else if (bcop == BCOp.EMBLEMCHANGE) {
Server.getInstance().getWorld(world).sendPacket(notifications.get(b), packet, exceptionId); Server.getInstance().getWorld(world).changeEmblem(this.id, notifications.get(b), new MapleGuildSummary(this));
} else {
Server.getInstance().getWorld(world).sendPacket(notifications.get(b), packet, exceptionId);
}
} }
} }
} catch (Exception re) {
re.printStackTrace();
System.out.println("Failed to contact channel(s) for broadcast.");//fu?
} }
} catch (Exception re) {
re.printStackTrace();
System.out.println("Failed to contact channel(s) for broadcast.");//fu?
} }
} finally {
membersLock.unlock();
} }
} }
+10 -6
View File
@@ -224,14 +224,18 @@ public class EventInstanceManager {
} }
public void registerPlayer(MapleCharacter chr) { public synchronized void registerPlayer(MapleCharacter chr) {
if (chr == null || !chr.isLoggedin()){ if (chr == null || !chr.isLoggedinWorld() || disposed) {
return; return;
} }
try { try {
wL.lock(); wL.lock();
try { try {
if(chars.containsKey(chr.getId())) {
return;
}
chars.put(chr.getId(), chr); chars.put(chr.getId(), chr);
chr.setEventInstance(this); chr.setEventInstance(this);
} finally { } finally {
@@ -249,7 +253,7 @@ public class EventInstanceManager {
} }
} }
public void exitPlayer(MapleCharacter chr) { //unused public void exitPlayer(MapleCharacter chr) {
if (chr == null || !chr.isLoggedin()){ if (chr == null || !chr.isLoggedin()){
return; return;
} }
@@ -299,7 +303,7 @@ public class EventInstanceManager {
sL.unlock(); sL.unlock();
} }
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement scheduledTimeout function.", ex);
} }
} }
}, time); }, time);
@@ -324,7 +328,7 @@ public class EventInstanceManager {
sL.unlock(); sL.unlock();
} }
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement scheduledTimeout function.", ex);
} }
} }
}, nextTime); }, nextTime);
@@ -397,7 +401,7 @@ public class EventInstanceManager {
sL.unlock(); sL.unlock();
} }
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement playerUnregistered function.", ex);
} }
wL.lock(); wL.lock();
+232 -122
View File
@@ -48,10 +48,14 @@ import server.life.MapleMonster;
import server.life.MapleLifeFactory; import server.life.MapleLifeFactory;
import server.quest.MapleQuest; import server.quest.MapleQuest;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import net.server.audit.LockCollector; import net.server.audit.LockCollector;
import net.server.audit.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
@@ -74,12 +78,16 @@ public class EventManager {
private final Map<Integer, Integer> queuedGuildLeaders = new HashMap<>(); private final Map<Integer, Integer> queuedGuildLeaders = new HashMap<>();
private List<Boolean> openedLobbys; private List<Boolean> openedLobbys;
private List<EventInstanceManager> readyInstances = new LinkedList<>(); private List<EventInstanceManager> readyInstances = new LinkedList<>();
private Integer readyId = 0; private Integer readyId = 0, onLoadInstances = 0;
private Properties props = new Properties(); private Properties props = new Properties();
private String name; private String name;
private MonitoredReentrantLock lobbyLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_LOBBY); private MonitoredReentrantLock lobbyLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_LOBBY);
private MonitoredReentrantLock queueLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_QUEUE); private MonitoredReentrantLock queueLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_QUEUE);
private MonitoredReentrantLock startLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_START);
private Set<Integer> playerPermit = new HashSet<>();
private Semaphore startSemaphore = new Semaphore(7);
private static final int maxLobbys = 8; // an event manager holds up to this amount of concurrent lobbys private static final int maxLobbys = 8; // an event manager holds up to this amount of concurrent lobbys
public EventManager(Channel cserv, Invocable iv, String name) { public EventManager(Channel cserv, Invocable iv, String name) {
@@ -114,6 +122,7 @@ public class EventManager {
try { try {
readyEims = new ArrayList<>(readyInstances); readyEims = new ArrayList<>(readyInstances);
readyInstances.clear(); readyInstances.clear();
onLoadInstances = Integer.MIN_VALUE / 2;
} finally { } finally {
queueLock.unlock(); queueLock.unlock();
} }
@@ -143,6 +152,7 @@ public class EventManager {
private void emptyLocks() { private void emptyLocks() {
lobbyLock = lobbyLock.dispose(); lobbyLock = lobbyLock.dispose();
queueLock = queueLock.dispose(); queueLock = queueLock.dispose();
startLock = startLock.dispose();
} }
private static List<Integer> convertToIntegerArray(List<Double> list) { private static List<Integer> convertToIntegerArray(List<Double> list) {
@@ -333,33 +343,50 @@ public class EventManager {
//Expedition method: starts an expedition //Expedition method: starts an expedition
public boolean startInstance(int lobbyId, MapleExpedition exped, MapleCharacter leader) { public boolean startInstance(int lobbyId, MapleExpedition exped, MapleCharacter leader) {
try { try {
if(lobbyId == -1) { if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
lobbyId = availableLobbyInstance(); playerPermit.add(leader.getId());
if(lobbyId == -1) return false;
} startLock.lock();
else { try {
if(!startLobbyInstance(lobbyId)) return false; try {
} if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", leader.getClient().getChannel())); if(lobbyId == -1) return false;
if(eim == null) { }
if(lobbyId > -1) { else {
setLockLobby(lobbyId, false); if(!startLobbyInstance(lobbyId)) return false;
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", leader.getClient().getChannel()));
if(eim == null) {
if(lobbyId > -1) {
setLockLobby(lobbyId, false);
}
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
exped.start();
eim.registerExpedition(exped);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
} finally {
startLock.unlock();
playerPermit.remove(leader.getId());
startSemaphore.release();
} }
return false;
} }
instanceLocks.put(eim.getName(), lobbyId); } catch(InterruptedException ie) {
eim.setLeader(leader); playerPermit.remove(leader.getId());
exped.start();
eim.registerExpedition(exped);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
return true; return false;
} }
//Regular method: player //Regular method: player
@@ -373,36 +400,53 @@ public class EventManager {
public boolean startInstance(int lobbyId, MapleCharacter chr, MapleCharacter leader, int difficulty) { public boolean startInstance(int lobbyId, MapleCharacter chr, MapleCharacter leader, int difficulty) {
try { try {
if(lobbyId == -1) { if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
lobbyId = availableLobbyInstance(); playerPermit.add(leader.getId());
if(lobbyId == -1) {
return false; startLock.lock();
try {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(lobbyId == -1) {
return false;
}
}
else {
if(!startLobbyInstance(lobbyId)) {
return false;
}
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : leader.getId()));
if(eim == null) {
if(lobbyId > -1) {
setLockLobby(lobbyId, false);
}
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
if(chr != null) eim.registerPlayer(chr);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
} finally {
startLock.unlock();
playerPermit.remove(leader.getId());
startSemaphore.release();
} }
} }
else { } catch(InterruptedException ie) {
if(!startLobbyInstance(lobbyId)) { playerPermit.remove(leader.getId());
return false;
}
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : leader.getId()));
if(eim == null) {
if(lobbyId > -1) {
setLockLobby(lobbyId, false);
}
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
if(chr != null) eim.registerPlayer(chr);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
return true; return false;
} }
//PQ method: starts a PQ //PQ method: starts a PQ
@@ -416,33 +460,50 @@ public class EventManager {
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, MapleCharacter leader) { public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, MapleCharacter leader) {
try { try {
if(lobbyId == -1) { if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
lobbyId = availableLobbyInstance(); playerPermit.add(leader.getId());
if(lobbyId == -1) return false;
} startLock.lock();
else { try {
if(!startLobbyInstance(lobbyId)) return false; try {
} if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null)); if(lobbyId == -1) return false;
if(eim == null) { }
if(lobbyId > -1) { else {
setLockLobby(lobbyId, false); if(!startLobbyInstance(lobbyId)) return false;
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
if(eim == null) {
if(lobbyId > -1) {
setLockLobby(lobbyId, false);
}
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
eim.registerParty(party, map);
party.setEligibleMembers(null);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
} finally {
startLock.unlock();
playerPermit.remove(leader.getId());
startSemaphore.release();
} }
return false;
} }
instanceLocks.put(eim.getName(), lobbyId); } catch(InterruptedException ie) {
eim.setLeader(leader); playerPermit.remove(leader.getId());
eim.registerParty(party, map);
party.setEligibleMembers(null);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
return true; return false;
} }
//PQ method: starts a PQ with a difficulty level, requires function setup(difficulty, leaderid) instead of setup() //PQ method: starts a PQ with a difficulty level, requires function setup(difficulty, leaderid) instead of setup()
@@ -456,33 +517,50 @@ public class EventManager {
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, int difficulty, MapleCharacter leader) { public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, int difficulty, MapleCharacter leader) {
try { try {
if(lobbyId == -1) { if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
lobbyId = availableLobbyInstance(); playerPermit.add(leader.getId());
if(lobbyId == -1) return false;
} startLock.lock();
else { try {
if(!startLobbyInstance(lobbyId)) return false; try {
} if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : party.getLeaderId())); if(lobbyId == -1) return false;
if(eim == null) { }
if(lobbyId > -1) { else {
setLockLobby(lobbyId, false); if(!startLobbyInstance(lobbyId)) return false;
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : party.getLeaderId()));
if(eim == null) {
if(lobbyId > -1) {
setLockLobby(lobbyId, false);
}
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
eim.registerParty(party, map);
party.setEligibleMembers(null);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
} finally {
startLock.unlock();
playerPermit.remove(leader.getId());
startSemaphore.release();
} }
return false;
} }
instanceLocks.put(eim.getName(), lobbyId); } catch(InterruptedException ie) {
eim.setLeader(leader); playerPermit.remove(leader.getId());
eim.registerParty(party, map);
party.setEligibleMembers(null);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
return true; return false;
} }
//non-PQ method for starting instance //non-PQ method for starting instance
@@ -500,32 +578,49 @@ public class EventManager {
public boolean startInstance(int lobbyId, EventInstanceManager eim, String ldr, MapleCharacter leader) { public boolean startInstance(int lobbyId, EventInstanceManager eim, String ldr, MapleCharacter leader) {
try { try {
if(lobbyId == -1) { if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
lobbyId = availableLobbyInstance(); playerPermit.add(leader.getId());
if(lobbyId == -1) return false;
} startLock.lock();
else { try {
if(!startLobbyInstance(lobbyId)) return false; try {
} if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(eim == null) { if(lobbyId == -1) return false;
if(lobbyId > -1) { }
setLockLobby(lobbyId, false); else {
if(!startLobbyInstance(lobbyId)) return false;
}
if(eim == null) {
if(lobbyId > -1) {
setLockLobby(lobbyId, false);
}
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
iv.invokeFunction("setup", eim);
eim.setProperty("leader", ldr);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
} finally {
startLock.unlock();
playerPermit.remove(leader.getId());
startSemaphore.release();
} }
return false;
} }
instanceLocks.put(eim.getName(), lobbyId); } catch(InterruptedException ie) {
eim.setLeader(leader); playerPermit.remove(leader.getId());
iv.invokeFunction("setup", eim);
eim.setProperty("leader", ldr);
eim.startEvent();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
return true; return false;
} }
public List<MaplePartyCharacter> getEligibleParty(MapleParty party) { public List<MaplePartyCharacter> getEligibleParty(MapleParty party) {
@@ -713,16 +808,31 @@ public class EventManager {
} }
private void instantiateQueuedInstance() { private void instantiateQueuedInstance() {
int nextEventId;
queueLock.lock(); queueLock.lock();
try { try {
if(readyInstances.size() >= Math.ceil((double)maxLobbys / 3.0)) return; if(onLoadInstances <= -1000 || readyInstances.size() + onLoadInstances >= Math.ceil((double)maxLobbys / 3.0)) return;
readyInstances.add(new EventInstanceManager(this, "sampleName" + readyId)); onLoadInstances++;
nextEventId = readyId;
readyId++; readyId++;
} finally { } finally {
queueLock.unlock(); queueLock.unlock();
} }
EventInstanceManager eim = new EventInstanceManager(this, "sampleName" + nextEventId);
queueLock.lock();
try {
if(onLoadInstances <= -1000) { // EM already disposed
return;
}
readyInstances.add(eim);
onLoadInstances--;
} finally {
queueLock.unlock();
}
instantiateQueuedInstance(); // keep filling the queue until reach threshold. instantiateQueuedInstance(); // keep filling the queue until reach threshold.
} }
@@ -344,7 +344,9 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
public void gainCloseness(int closeness) { public void gainCloseness(int closeness) {
for (MaplePet pet : getPlayer().getPets()) { for (MaplePet pet : getPlayer().getPets()) {
if(pet != null) pet.gainClosenessFullness(getPlayer(), closeness, 0, 0); if(pet != null) {
pet.gainClosenessFullness(getPlayer(), closeness, 0, 0);
}
} }
} }
+1 -1
View File
@@ -38,7 +38,7 @@ import client.MapleCharacter;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class MapleExpedition { public class MapleExpedition {
@@ -26,7 +26,7 @@ import constants.ServerConstants;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public enum MapleExpeditionType { public enum MapleExpeditionType {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class Ellinia extends GachaponItems { public class Ellinia extends GachaponItems {
+1 -1
View File
@@ -24,7 +24,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public abstract class GachaponItems { public abstract class GachaponItems {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class Global extends GachaponItems { public class Global extends GachaponItems {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class Henesys extends GachaponItems { public class Henesys extends GachaponItems {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class KerningCity extends GachaponItems { public class KerningCity extends GachaponItems {
+1 -1
View File
@@ -25,7 +25,7 @@ import tools.Randomizer;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class MapleGachapon { public class MapleGachapon {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class MushroomShrine extends GachaponItems { public class MushroomShrine extends GachaponItems {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class NautilusHarbor extends GachaponItems { public class NautilusHarbor extends GachaponItems {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class NewLeafCity extends GachaponItems { public class NewLeafCity extends GachaponItems {
+1 -1
View File
@@ -2,7 +2,7 @@ package server.gachapon;
/** /**
* *
* @author SharpAceX(Alan) * @author Alan (SharpAceX)
*/ */
public class Perion extends GachaponItems { public class Perion extends GachaponItems {

Some files were not shown because too many files have changed in this diff Show More